From 69ed114d388c56e83a2385d8b8182e6d05a0b073 Mon Sep 17 00:00:00 2001 From: wangyix Date: Tue, 18 Aug 2015 07:24:29 -0700 Subject: [PATCH] Added class AutoFragmentChildProcAdvance to be constructed before a child emitCode and destructed after Fixed wrong indent Changed auto child advance back to backwards linear search for getting subset of coords and samplers array of a child Used offset from parent instead of backwards linear search to find a child proc's coords and transforms in Auto...Advance append mangleString to variable name in nameVariable() BUILDS! Added AutoFragmentChildProcAdvance class; fixed a few errors from previous commits BUG=skia:4182 Review URL: https://codereview.chromium.org/1286293002 --- include/gpu/GrFragmentProcessor.h | 22 ++++- .../gl/builders/GrGLFragmentShaderBuilder.cpp | 82 +++++++++++++++++++ .../gl/builders/GrGLFragmentShaderBuilder.h | 31 +++++++ src/gpu/gl/builders/GrGLProgramBuilder.cpp | 2 +- 4 files changed, 134 insertions(+), 3 deletions(-) diff --git a/include/gpu/GrFragmentProcessor.h b/include/gpu/GrFragmentProcessor.h index bbc2f2bb07..4b2f96d7f9 100644 --- a/include/gpu/GrFragmentProcessor.h +++ b/include/gpu/GrFragmentProcessor.h @@ -152,8 +152,26 @@ private: bool fUsesLocalCoords; /** - * This stores the transforms of this proc, followed by all the transforms of this proc's - * children. In other words, each proc stores all the transforms of its subtree. + * fCoordTransforms stores the transforms of this proc, followed by all the transforms of this + * proc's children. In other words, each proc stores all the transforms of its subtree as if + * they were collected using preorder traversal. + * + * Example: + * Suppose we have frag proc A, who has two children B and D. B has a child C, and D has + * two children E and F. Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms + * respectively. The following shows what the fCoordTransforms array of each proc would contain: + * + * (A) + * [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2] + * / \ + * / \ + * (B) (D) + * [b1,b2,c1] [d1,e1,e2,e3,f1,f2] + * / / \ + * / / \ + * (C) (E) (F) + * [c1] [e1,e2,e3] [f1,f2] + * * The same goes for fTextureAccesses with textures. */ SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp index 20bb3a3893..71434154dd 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.cpp @@ -312,3 +312,85 @@ void GrGLFragmentBuilder::onAfterChildProcEmitCode() { int removeAt = fMangleString.findLastOf('_'); fMangleString.remove(removeAt, fMangleString.size() - removeAt); } + +GrGLFragmentBuilder::AutoFragmentChildProcAdvance::AutoFragmentChildProcAdvance( + int childProcIndex, + GrGLFPBuilder* builder, + const GrFragmentProcessor& fp, + const char* outputColor, + const TransformedCoordsArray& coords, + const TextureSamplerArray& samplers, + const GrFragmentProcessor** childFp, + SkString* childOutputColor, + TransformedCoordsArray* childCoords, + TextureSamplerArray* childSamplers + ) { + fFsb = builder->getFragmentShaderBuilder(); + fFsb->onBeforeChildProcEmitCode(); // call first so mangleString is updated + + const GrFragmentProcessor& childProc = fp.childProcessor(childProcIndex); + *childFp = &childProc; + + // Mangle the name of the outputColor + childOutputColor->set(outputColor); + childOutputColor->append(fFsb->getMangleStringThisLevel()); + + /* + * We now want to find the subset of coords and samplers that belong to the child and its + * descendants and put that into childCoords and childSamplers. To do so, we must do a + * backwards linear search on coords and samplers. + * + * Explanation: + * Each GrFragmentProcessor has a copy of all the transforms and textures of itself and + * all procs in its subtree. For example, suppose we have frag proc A, who has two children B + * and D. B has a child C, and D has two children E and F. Each frag proc's transforms array + * contains its own transforms, followed by the transforms of all its descendants (i.e. preorder + * traversal). Suppose procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 transforms respectively. + * + * (A) + * [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2] + * / \ + * / \ + * (B) (D) + * [b1,b2,c1] [d1,e1,e2,e3,f1,f2] + * / / \ + * / / \ + * (C) (E) (F) + * [c1] [e1,e2,e3] [f1,f2] + * + * So if we're inside proc A's emitCode, and A is about to call emitCode on proc B, we want the + * EmitArgs that's passed onto B to only contain its and its descendants' coords. The + * EmitArgs given to A would contain the transforms [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want + * to extract the subset [b1,b2,c1] to pass on to B. We can do this with a backwards linear + * search since we know that D's subtree has 6 transforms and B's subtree has 3 transforms (by + * calling D.numTextures() and B.numTextures()), so we know the start of B's transforms is 9 + * from the end of A's transforms. We cannot do this with a forwards linear search since we + * don't know how many transforms belong to A (A.numTextures() will return 10, not 1), so + * we wouldn't know how many transforms to initially skip in A's array if using a forward linear + * search. + * Textures work the same way as transforms. + */ + SkASSERT(childCoords->empty()); + SkASSERT(childSamplers->empty()); + int firstCoordAt = fp.numTransforms(); + int firstSamplerAt = fp.numTextures(); + for (int i = fp.numChildProcessors() - 1; i >= childProcIndex; --i) { + firstCoordAt -= fp.childProcessor(i).numTransforms(); + firstSamplerAt -= fp.childProcessor(i).numTextures(); + } + if (!coords.empty()) { + childCoords->push_back_n(childProc.numTransforms(), &coords[firstCoordAt]); + } + if (!samplers.empty()) { + childSamplers->push_back_n(childProc.numTextures(), &samplers[firstSamplerAt]); + } + + fFsb->codeAppendf("vec4 %s;\n", childOutputColor->c_str()); + fFsb->codeAppend("{\n"); + fFsb->codeAppendf("// Child %d: %s\n", fFsb->getChildNumberThisLevel(), childProc.name()); +} + +GrGLFragmentBuilder::AutoFragmentChildProcAdvance::~AutoFragmentChildProcAdvance() { + fFsb->codeAppend("}\n"); + fFsb->onAfterChildProcEmitCode(); +} diff --git a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h index 8746fffb8b..514bcc6e88 100644 --- a/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h +++ b/src/gpu/gl/builders/GrGLFragmentShaderBuilder.h @@ -77,6 +77,37 @@ public: return ret; } + /* This class is like AutoStageAdvance but used for the child procs of a fragment proc. + * Before a proc calls emitCode on one of its children, it should instantiate this + * class inside its own scope. This which will update a state in GrGLFragmentBuilder that tracks + * which proc in the tree is about to emit code (it does so by calling GrGLFragmentBuilder:: + * onBeforeChildProcEmitCode() in the constructor). + * + * After the child proc emitCode is called, the parent proc should end the scope so the + * AutoFragmentChildProcAdvance destructor is called, which will again update a state in + * GrGLFragmentShaderBuilder notifying it that the child proc's code has been emitted (it does + * so by calling GrGLFragmentBuilder::onAfterChildProcEmitCode()). + */ + class AutoFragmentChildProcAdvance { + typedef GrGLProcessor::TransformedCoordsArray TransformedCoordsArray; + typedef GrGLProcessor::TextureSamplerArray TextureSamplerArray; + public: + AutoFragmentChildProcAdvance(int childProcIndex, + GrGLFPBuilder* builder, + const GrFragmentProcessor& fp, + const char* outputColor, + const TransformedCoordsArray& coords, + const TextureSamplerArray& samplers, + const GrFragmentProcessor** childFp, + SkString* childOutputColor, + TransformedCoordsArray* childCoords, + TextureSamplerArray* childSamplers); + + ~AutoFragmentChildProcAdvance(); + private: + GrGLFragmentBuilder* fFsb; + }; + private: /* * State that tracks which child proc in the proc tree is currently emitting code. This is diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp index 079b129cb1..2db568693d 100644 --- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp +++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp @@ -124,7 +124,7 @@ void GrGLProgramBuilder::nameVariable(SkString* out, char prefix, const char* na // Names containing "__" are reserved. out->append("x"); } - out->appendf("_Stage%d", fStageIndex); + out->appendf("_Stage%d%s", fStageIndex, fFS.getMangleString().c_str()); } } -- 2.34.1