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:
parent
94c902e63d
commit
69ed114d38
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user