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
This commit is contained in:
wangyix 2015-08-18 07:24:29 -07:00 committed by Commit bot
parent 94c902e63d
commit 69ed114d38
4 changed files with 134 additions and 3 deletions

View File

@ -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;

View File

@ -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();
}

View File

@ -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

View File

@ -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());
}
}