From a624bf3d1cb454c1959c5bbbf23a3afdfa3481f3 Mon Sep 17 00:00:00 2001 From: bsalomon Date: Tue, 20 Sep 2016 09:12:47 -0700 Subject: Stop flattening GrCoordTransforms in parent GrFragmentProcessors. This changes moves to a model that iterates over GrCTs in a GrFP hierarchy when inserting transformations by GrGLSLPrimitiveProcessors. GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2339203002 Committed: https://skia.googlesource.com/skia/+/d91237ee051523f439238042674ade99207fe4a6 Review-Url: https://codereview.chromium.org/2339203002 --- src/gpu/glsl/GrGLSLFragmentProcessor.cpp | 53 ++++++++------ src/gpu/glsl/GrGLSLFragmentProcessor.h | 32 +++++++-- src/gpu/glsl/GrGLSLGeometryProcessor.cpp | 113 ++++++++++++++++-------------- src/gpu/glsl/GrGLSLGeometryProcessor.h | 32 ++------- src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp | 13 ++++ src/gpu/glsl/GrGLSLPrimitiveProcessor.h | 72 +++++++++++++------ src/gpu/glsl/GrGLSLProgramBuilder.cpp | 42 +++++------ src/gpu/glsl/GrGLSLProgramBuilder.h | 12 ++-- 8 files changed, 218 insertions(+), 151 deletions(-) (limited to 'src/gpu/glsl') diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp index 9a58db77bd..82a07ca39d 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp @@ -43,16 +43,16 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex); /* - * 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'll do a forwards - * linear search. + * TODO: Move textures and buffers to the iterator model used by coords. + * We now want to find the subset of samplers that belong to the child and its descendants and + * put that into childSamplers. To do so, we'll do a forwards linear search. * * 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. + * Each GrFragmentProcessor has a copy of all the 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 textures array contains its own + * textures, followed by the textures of all its descendants (i.e. preorder traversal). Suppose + * procs A, B, C, D, E, F have 1, 2, 1, 1, 3, 2 textures respectively. * * (A) * [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2] @@ -66,28 +66,22 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu * [c1] [e1,e2,e3] [f1,f2] * * So if we're inside proc A's emitCode, and A is about to call emitCode on proc D, we want the - * EmitArgs that's passed onto D 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 + * EmitArgs that's passed onto D to only contain its and its descendants' textures. The + * EmitArgs given to A would contain the textures [a1,b1,b2,c1,d1,e1,e2,e3,f1,f2], and we want * to extract the subset [d1,e1,e2,e3,f1,f2] to pass on to D. We can do this with a linear - * search since we know that A has 1 transform (using A.numTransformsExclChildren()), and B's - * subtree has 3 transforms (using B.numTransforms()), so we know the start of D's transforms is - * 4 after the start of A's transforms. - * Textures work the same way as transforms. + * search since we know that A has 1 texture (using A.numTexturesExclChildren()), and B's + * subtree has 3 textures (using B.numTextures()), so we know the start of D's textures is + * 4 after the start of A's textures. + * Textures work the same way as textures. */ - int firstCoordAt = args.fFp.numTransformsExclChildren(); int firstTextureAt = args.fFp.numTexturesExclChildren(); int firstBufferAt = args.fFp.numBuffersExclChildren(); for (int i = 0; i < childIndex; ++i) { - firstCoordAt += args.fFp.childProcessor(i).numTransforms(); firstTextureAt += args.fFp.childProcessor(i).numTextures(); firstBufferAt += args.fFp.childProcessor(i).numBuffers(); } - SkTArray childCoords; const SamplerHandle* childTexSamplers = nullptr; const SamplerHandle* childBufferSamplers = nullptr; - if (childProc.numTransforms() > 0) { - childCoords.push_back_n(childProc.numTransforms(), &args.fTransformedCoords[firstCoordAt]); - } if (childProc.numTextures() > 0) { childTexSamplers = &args.fTexSamplers[firstTextureAt]; } @@ -99,13 +93,14 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu fragBuilder->codeAppend("{\n"); fragBuilder->codeAppendf("// Child Index %d (mangle: %s): %s\n", childIndex, fragBuilder->getMangleString().c_str(), childProc.name()); + TransformedCoordVars coordVars = args.fTransformedCoords.childTransforms(childIndex); EmitArgs childArgs(fragBuilder, args.fUniformHandler, args.fGLSLCaps, childProc, outputColor, inputColor, - childCoords, + coordVars, childTexSamplers, childBufferSamplers, args.fGpImplementsDistanceVector); @@ -114,3 +109,19 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu fragBuilder->onAfterChildProcEmitCode(); } + +////////////////////////////////////////////////////////////////////////////// + +using TransformedCoordVars = GrGLSLFragmentProcessor::TransformedCoordVars; +TransformedCoordVars TransformedCoordVars::childTransforms(int childIdx) const { + const GrFragmentProcessor* child = &fFP->childProcessor(childIdx); + GrFragmentProcessor::Iter iter(fFP); + int numToSkip = 0; + while (true) { + const GrFragmentProcessor* fp = iter.next(); + if (fp == child) { + return TransformedCoordVars(child, fTransformedVars + numToSkip); + } + numToSkip += fp->numCoordTransforms(); + } +} diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h index f4a93ebe71..9889bcc9c6 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.h +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h @@ -33,6 +33,30 @@ public: typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle; + /** + * When building a program from a GrPipeline this is used to provide the GrShaderVars that + * contain the resulting transformed coords from each of a GrFragmentProcessor's + * GrCoordTransforms. This allows the GrFragmentProcessor subclasses to refer to the transformed + * coords in fragment code. + */ + class TransformedCoordVars { + public: + TransformedCoordVars(const GrFragmentProcessor* fp, const GrShaderVar* vars) + : fFP(fp) + , fTransformedVars(vars) {} + + const GrShaderVar& operator[] (int i) const { + SkASSERT(i >= 0 && i < fFP->numCoordTransforms()); + return fTransformedVars[i]; + } + + TransformedCoordVars childTransforms(int childIdx) const; + + private: + const GrFragmentProcessor* fFP; + const GrShaderVar* fTransformedVars; + }; + /** Called when the program stage should insert its code into the shaders. The code in each shader will be in its own block ({}) and so locally scoped names will not collide across stages. @@ -50,7 +74,7 @@ public: etc.) that allows the processor to communicate back similar known info about its output. @param transformedCoords Fragment shader variables containing the coords computed using - each of the GrFragmentProcessor's Coord Transforms. + each of the GrFragmentProcessor's GrCoordTransforms. @param texSamplers Contains one entry for each GrTextureAccess of the GrProcessor. These can be passed to the builder to emit texture reads in the generated code. @@ -65,7 +89,7 @@ public: const GrFragmentProcessor& fp, const char* outputColor, const char* inputColor, - const SkTArray& transformedCoords, + const TransformedCoordVars& transformedCoordVars, const SamplerHandle* texSamplers, const SamplerHandle* bufferSamplers, bool gpImplementsDistanceVector) @@ -75,7 +99,7 @@ public: , fFp(fp) , fOutputColor(outputColor) , fInputColor(inputColor) - , fTransformedCoords(transformedCoords) + , fTransformedCoords(transformedCoordVars) , fTexSamplers(texSamplers) , fBufferSamplers(bufferSamplers) , fGpImplementsDistanceVector(gpImplementsDistanceVector) {} @@ -85,7 +109,7 @@ public: const GrFragmentProcessor& fFp; const char* fOutputColor; const char* fInputColor; - const SkTArray& fTransformedCoords; + const TransformedCoordVars& fTransformedCoords; const SamplerHandle* fTexSamplers; const SamplerHandle* fBufferSamplers; bool fGpImplementsDistanceVector; diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp index ddbe8e133a..bea49e5069 100644 --- a/src/gpu/glsl/GrGLSLGeometryProcessor.cpp +++ b/src/gpu/glsl/GrGLSLGeometryProcessor.cpp @@ -29,71 +29,82 @@ void GrGLSLGeometryProcessor::emitTransforms(GrGLSLVertexBuilder* vb, const GrShaderVar& posVar, const char* localCoords, const SkMatrix& localMatrix, - const TransformsIn& tin, - TransformsOut* tout) { - tout->push_back_n(tin.count()); - fInstalledTransforms.push_back_n(tin.count()); - for (int i = 0; i < tin.count(); i++) { - const ProcCoords& coordTransforms = tin[i]; - fInstalledTransforms[i].push_back_n(coordTransforms.count()); - for (int t = 0; t < coordTransforms.count(); t++) { - SkString strUniName("StageMatrix"); - strUniName.appendf("_%i_%i", i, t); - GrSLType varyingType; + FPCoordTransformHandler* handler) { + int i = 0; + while (const GrCoordTransform* coordTransform = handler->nextCoordTransform()) { + SkString strUniName; + strUniName.printf("CoordTransformMatrix_%d", i); + GrSLType varyingType; - GrCoordSet coordType = coordTransforms[t]->sourceCoords(); - uint32_t type = coordTransforms[t]->getMatrix().getType(); - if (kLocal_GrCoordSet == coordType) { - type |= localMatrix.getType(); - } - varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType : - kVec2f_GrSLType; - GrSLPrecision precision = coordTransforms[t]->precision(); + GrCoordSet coordType = coordTransform->sourceCoords(); + uint32_t type = coordTransform->getMatrix().getType(); + if (kLocal_GrCoordSet == coordType) { + type |= localMatrix.getType(); + } + varyingType = SkToBool(SkMatrix::kPerspective_Mask & type) ? kVec3f_GrSLType : + kVec2f_GrSLType; + GrSLPrecision precision = coordTransform->precision(); + + const char* uniName; - const char* uniName; - fInstalledTransforms[i][t].fHandle = - uniformHandler->addUniform(kVertex_GrShaderFlag, - kMat33f_GrSLType, precision, - strUniName.c_str(), - &uniName).toIndex(); - SkString strVaryingName("MatrixCoord"); - strVaryingName.appendf("_%i_%i", i, t); + fInstalledTransforms.push_back().fHandle = uniformHandler->addUniform(kVertex_GrShaderFlag, + kMat33f_GrSLType, + precision, + strUniName.c_str(), + &uniName).toIndex(); + SkString strVaryingName; + strVaryingName.printf("TransformedCoords_%d", i); - GrGLSLVertToFrag v(varyingType); - varyingHandler->addVarying(strVaryingName.c_str(), &v, precision); + GrGLSLVertToFrag v(varyingType); + varyingHandler->addVarying(strVaryingName.c_str(), &v, precision); - SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); - (*tout)[i].emplace_back(SkString(v.fsIn()), varyingType); + SkASSERT(kVec2f_GrSLType == varyingType || kVec3f_GrSLType == varyingType); + handler->specifyCoordsForCurrCoordTransform(SkString(v.fsIn()), varyingType); - // varying = matrix * coords (logically) - if (kDevice_GrCoordSet == coordType) { - if (kVec2f_GrSLType == varyingType) { - if (kVec2f_GrSLType == posVar.getType()) { - vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", - v.vsOut(), uniName, posVar.c_str()); - } else { - // The brackets here are just to scope the temp variable - vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str()); - vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut()); - } + // varying = matrix * coords (logically) + if (kDevice_GrCoordSet == coordType) { + if (kVec2f_GrSLType == varyingType) { + if (kVec2f_GrSLType == posVar.getType()) { + vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", + v.vsOut(), uniName, posVar.c_str()); } else { - if (kVec2f_GrSLType == posVar.getType()) { - vb->codeAppendf("%s = %s * vec3(%s, 1);", - v.vsOut(), uniName, posVar.c_str()); - } else { - vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str()); - } + // The brackets here are just to scope the temp variable + vb->codeAppendf("{ vec3 temp = %s * %s;", uniName, posVar.c_str()); + vb->codeAppendf("%s = vec2(temp.x/temp.z, temp.y/temp.z); }", v.vsOut()); } } else { - if (kVec2f_GrSLType == varyingType) { - vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords); + if (kVec2f_GrSLType == posVar.getType()) { + vb->codeAppendf("%s = %s * vec3(%s, 1);", + v.vsOut(), uniName, posVar.c_str()); } else { - vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords); + vb->codeAppendf("%s = %s * %s;", v.vsOut(), uniName, posVar.c_str()); } } + } else { + if (kVec2f_GrSLType == varyingType) { + vb->codeAppendf("%s = (%s * vec3(%s, 1)).xy;", v.vsOut(), uniName, localCoords); + } else { + vb->codeAppendf("%s = %s * vec3(%s, 1);", v.vsOut(), uniName, localCoords); + } + } + ++i; + } +} + +void GrGLSLGeometryProcessor::setTransformDataHelper(const SkMatrix& localMatrix, + const GrGLSLProgramDataManager& pdman, + FPCoordTransformIter* transformIter) { + int i = 0; + while (const GrCoordTransform* coordTransform = transformIter->next()) { + const SkMatrix& m = GetTransformMatrix(localMatrix, *coordTransform); + if (!fInstalledTransforms[i].fCurrentValue.cheapEqualTo(m)) { + pdman.setSkMatrix(fInstalledTransforms[i].fHandle.toIndex(), m); + fInstalledTransforms[i].fCurrentValue = m; } + ++i; } + SkASSERT(i == fInstalledTransforms.count()); } void GrGLSLGeometryProcessor::setupPosition(GrGLSLVertexBuilder* vertBuilder, diff --git a/src/gpu/glsl/GrGLSLGeometryProcessor.h b/src/gpu/glsl/GrGLSLGeometryProcessor.h index d1e715f78a..6777620a88 100644 --- a/src/gpu/glsl/GrGLSLGeometryProcessor.h +++ b/src/gpu/glsl/GrGLSLGeometryProcessor.h @@ -22,31 +22,11 @@ public: /* Any general emit code goes in the base class emitCode. Subclasses override onEmitCode */ void emitCode(EmitArgs&) override; - // By default we use the identity matrix - void setTransformData(const GrPrimitiveProcessor&, - const GrGLSLProgramDataManager& pdman, - int index, - const SkTArray& transforms) override { - this->setTransformDataHelper(SkMatrix::I(), pdman, index, transforms); - } - protected: // A helper which subclasses can use if needed and used above in the default setTransformData(). void setTransformDataHelper(const SkMatrix& localMatrix, const GrGLSLProgramDataManager& pdman, - int index, - const SkTArray& transforms) { - SkTArray& procTransforms = fInstalledTransforms[index]; - int numTransforms = transforms.count(); - for (int t = 0; t < numTransforms; ++t) { - SkASSERT(procTransforms[t].fHandle.isValid()); - const SkMatrix& transform = GetTransformMatrix(localMatrix, *transforms[t]); - if (!procTransforms[t].fCurrentValue.cheapEqualTo(transform)) { - pdman.setSkMatrix(procTransforms[t].fHandle.toIndex(), transform); - procTransforms[t].fCurrentValue = transform; - } - } - } + FPCoordTransformIter*); // Emit a uniform matrix for each coord transform. void emitTransforms(GrGLSLVertexBuilder* vb, @@ -54,10 +34,9 @@ protected: GrGLSLUniformHandler* uniformHandler, const GrShaderVar& posVar, const char* localCoords, - const TransformsIn& tin, - TransformsOut* tout) { + FPCoordTransformHandler* handler) { this->emitTransforms(vb, varyingHandler, uniformHandler, - posVar, localCoords, SkMatrix::I(), tin, tout); + posVar, localCoords, SkMatrix::I(), handler); } // Emit pre-transformed coords as a vertex attribute per coord-transform. @@ -67,8 +46,7 @@ protected: const GrShaderVar& posVar, const char* localCoords, const SkMatrix& localMatrix, - const TransformsIn&, - TransformsOut*); + FPCoordTransformHandler*); struct GrGPArgs { // The variable used by a GP to store its position. It can be @@ -103,7 +81,7 @@ private: SkMatrix fCurrentValue = SkMatrix::InvalidMatrix(); }; - SkSTArray<8, SkSTArray<2, TransformUniform, true> > fInstalledTransforms; + SkTArray fInstalledTransforms; typedef GrGLSLPrimitiveProcessor INHERITED; }; diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp index c19239a5d5..5ae28a0bbc 100644 --- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp +++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.cpp @@ -47,3 +47,16 @@ void GrGLSLPrimitiveProcessor::setupUniformColor(GrGLSLPPFragmentBuilder* fragBu &stagedLocalVarName); fragBuilder->codeAppendf("%s = %s;", outputName, stagedLocalVarName); } + +////////////////////////////////////////////////////////////////////////////// + +const GrCoordTransform* GrGLSLPrimitiveProcessor::FPCoordTransformHandler::nextCoordTransform() { +#ifdef SK_DEBUG + SkASSERT(nullptr == fCurr || fAddedCoord); + fAddedCoord = false; + fCurr = fIter.next(); + return fCurr; +#else + return fIter.next(); +#endif +} diff --git a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h index 6f3381f996..d270fa18fe 100644 --- a/src/gpu/glsl/GrGLSLPrimitiveProcessor.h +++ b/src/gpu/glsl/GrGLSLPrimitiveProcessor.h @@ -8,6 +8,7 @@ #ifndef GrGLSLPrimitiveProcessor_DEFINED #define GrGLSLPrimitiveProcessor_DEFINED +#include "GrFragmentProcessor.h" #include "GrPrimitiveProcessor.h" #include "glsl/GrGLSLProgramDataManager.h" #include "glsl/GrGLSLSampler.h" @@ -23,14 +24,45 @@ class GrGLSLVertexBuilder; class GrGLSLPrimitiveProcessor { public: + using FPCoordTransformIter = GrFragmentProcessor::CoordTransformIter; + virtual ~GrGLSLPrimitiveProcessor() {} typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle; - typedef SkSTArray<2, const GrCoordTransform*, true> ProcCoords; - typedef SkSTArray<8, ProcCoords> TransformsIn; - typedef SkSTArray<8, SkTArray> TransformsOut; + /** + * This class provides access to the GrCoordTransforms across all GrFragmentProcessors in a + * GrPipeline. It is also used by the primitive processor to specify the fragment shader + * variable that will hold the transformed coords for each GrCoordTransform. It is required that + * the primitive processor iterate over each coord transform and insert a shader var result for + * each. The GrGLSLFragmentProcessors will reference these variables in their fragment code. + */ + class FPCoordTransformHandler : public SkNoncopyable { + public: + FPCoordTransformHandler(const GrPipeline& pipeline, + SkTArray* transformedCoordVars) + : fIter(pipeline) + , fTransformedCoordVars(transformedCoordVars) {} + + ~FPCoordTransformHandler() { SkASSERT(!this->nextCoordTransform());} + + const GrCoordTransform* nextCoordTransform(); + + // 'args' are constructor params to GrShaderVar. + template + void specifyCoordsForCurrCoordTransform(Args&&... args) { + SkASSERT(!fAddedCoord); + fTransformedCoordVars->emplace_back(std::forward(args)...); + SkDEBUGCODE(fAddedCoord = true;) + } + + private: + GrFragmentProcessor::CoordTransformIter fIter; + SkDEBUGCODE(bool fAddedCoord = false;) + SkDEBUGCODE(const GrCoordTransform* fCurr = nullptr;) + SkTArray* fTransformedCoordVars; + }; struct EmitArgs { EmitArgs(GrGLSLVertexBuilder* vertBuilder, @@ -44,8 +76,7 @@ public: const char* distanceVectorName, const SamplerHandle* texSamplers, const SamplerHandle* bufferSamplers, - const TransformsIn& transformsIn, - TransformsOut* transformsOut) + FPCoordTransformHandler* transformHandler) : fVertBuilder(vertBuilder) , fFragBuilder(fragBuilder) , fVaryingHandler(varyingHandler) @@ -57,8 +88,7 @@ public: , fDistanceVectorName(distanceVectorName) , fTexSamplers(texSamplers) , fBufferSamplers(bufferSamplers) - , fTransformsIn(transformsIn) - , fTransformsOut(transformsOut) {} + , fFPCoordTransformHandler(transformHandler) {} GrGLSLVertexBuilder* fVertBuilder; GrGLSLPPFragmentBuilder* fFragBuilder; GrGLSLVaryingHandler* fVaryingHandler; @@ -70,8 +100,7 @@ public: const char* fDistanceVectorName; const SamplerHandle* fTexSamplers; const SamplerHandle* fBufferSamplers; - const TransformsIn& fTransformsIn; - TransformsOut* fTransformsOut; + FPCoordTransformHandler* fFPCoordTransformHandler; }; /** @@ -80,21 +109,22 @@ public: */ virtual void emitCode(EmitArgs&) = 0; - /** A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that - produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and - uploads any uniform variables required by the shaders created in emitCode(). The - GrPrimitiveProcessor parameter is guaranteed to be of the same type that created this - GrGLSLPrimitiveProcessor and to have an identical processor key as the one that created this - GrGLSLPrimitiveProcessor. */ - virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&) = 0; + /** + * A GrGLSLPrimitiveProcessor instance can be reused with any GrGLSLPrimitiveProcessor that + * produces the same stage key; this function reads data from a GrGLSLPrimitiveProcessor and + * uploads any uniform variables required by the shaders created in emitCode(). The + * GrPrimitiveProcessor parameter is guaranteed to be of the same type and to have an + * identical processor key as the GrPrimitiveProcessor that created this + * GrGLSLPrimitiveProcessor. + * The subclass may use the transform iterator to perform any setup required for the particular + * set of fp transform matrices, such as uploading via uniforms. The iterator will iterate over + * the transforms in the same order as the TransformHandler passed to emitCode. + */ + virtual void setData(const GrGLSLProgramDataManager&, const GrPrimitiveProcessor&, + FPCoordTransformIter&&) = 0; static SkMatrix GetTransformMatrix(const SkMatrix& localMatrix, const GrCoordTransform&); - virtual void setTransformData(const GrPrimitiveProcessor&, - const GrGLSLProgramDataManager& pdman, - int index, - const SkTArray& transforms) = 0; - protected: void setupUniformColor(GrGLSLPPFragmentBuilder* fragBuilder, GrGLSLUniformHandler* uniformHandler, diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index 4d442f9752..29470c4e2b 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -53,19 +53,9 @@ bool GrGLSLProgramBuilder::emitAndInstallProcs(GrGLSLExpr4* inputColor, // be sent to the GrGLSLPrimitiveProcessor in its emitCode function const GrPrimitiveProcessor& primProc = this->primitiveProcessor(); - for (int i = 0; i < this->pipeline().numFragmentProcessors(); i++) { - const GrFragmentProcessor& processor = this->pipeline().getFragmentProcessor(i); - - SkTArray& procCoords = fCoordTransforms.push_back(); - processor.gatherCoordTransforms(&procCoords); - } - this->emitAndInstallPrimProc(primProc, inputColor, inputCoverage); - int numProcs = this->pipeline().numFragmentProcessors(); - this->emitAndInstallFragProcs(0, this->pipeline().numColorFragmentProcessors(), inputColor); - this->emitAndInstallFragProcs(this->pipeline().numColorFragmentProcessors(), numProcs, - inputCoverage); + this->emitAndInstallFragProcs(inputColor, inputCoverage); if (primProc.getPixelLocalStorageState() != GrPixelLocalStorageState::kDraw_GrPixelLocalStorageState) { this->emitAndInstallXferProc(this->pipeline().getXferProcessor(), *inputColor, @@ -109,6 +99,8 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr SkSTArray<2, SamplerHandle> bufferSamplers(proc.numBuffers()); this->emitSamplers(proc, &texSamplers, &bufferSamplers); + GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline, + &fTransformedCoordVars); GrGLSLGeometryProcessor::EmitArgs args(&fVS, &fFS, this->varyingHandler(), @@ -120,8 +112,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr distanceVectorName, texSamplers.begin(), bufferSamplers.begin(), - fCoordTransforms, - &fOutCoords); + &transformHandler); fGeometryProcessor->emitCode(args); // We have to check that effects and the code they emit are consistent, ie if an effect @@ -131,14 +122,21 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr fFS.codeAppend("}"); } -void GrGLSLProgramBuilder::emitAndInstallFragProcs(int procOffset, - int numProcs, - GrGLSLExpr4* inOut) { - for (int i = procOffset; i < numProcs; ++i) { +void GrGLSLProgramBuilder::emitAndInstallFragProcs(GrGLSLExpr4* color, GrGLSLExpr4* coverage) { + int transformedCoordVarsIdx = 0; + GrGLSLExpr4** inOut = &color; + for (int i = 0; i < this->pipeline().numFragmentProcessors(); ++i) { + if (i == this->pipeline().numColorFragmentProcessors()) { + inOut = &coverage; + } GrGLSLExpr4 output; const GrFragmentProcessor& fp = this->pipeline().getFragmentProcessor(i); - this->emitAndInstallFragProc(fp, i, *inOut, &output); - *inOut = output; + this->emitAndInstallFragProc(fp, i, transformedCoordVarsIdx, **inOut, &output); + GrFragmentProcessor::Iter iter(&fp); + while (const GrFragmentProcessor* fp = iter.next()) { + transformedCoordVarsIdx += fp->numCoordTransforms(); + } + **inOut = output; } } @@ -146,6 +144,7 @@ void GrGLSLProgramBuilder::emitAndInstallFragProcs(int procOffset, // the fix is to allow effects to take the GrGLSLExpr4 directly void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, int index, + int transformedCoordVarsIdx, const GrGLSLExpr4& input, GrGLSLExpr4* output) { // Program builders have a bit of state we need to clear with each effect @@ -163,13 +162,15 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, SkSTArray<2, SamplerHandle> bufferSamplers(fp.numBuffers()); this->emitSamplers(fp, &texSamplers, &bufferSamplers); + const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx; + GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars); GrGLSLFragmentProcessor::EmitArgs args(&fFS, this->uniformHandler(), this->glslCaps(), fp, output->c_str(), input.isOnes() ? nullptr : input.c_str(), - fOutCoords[index], + coords, texSamplers.begin(), bufferSamplers.begin(), this->primitiveProcessor().implementsDistanceVector()); @@ -418,5 +419,4 @@ void GrGLSLProgramBuilder::finalizeShaders() { this->varyingHandler()->finalize(); fVS.finalize(kVertex_GrShaderFlag); fFS.finalize(kFragment_GrShaderFlag); - } diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h index 27c84372c1..8a8cff55ad 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.h +++ b/src/gpu/glsl/GrGLSLProgramBuilder.h @@ -139,9 +139,10 @@ private: void emitAndInstallPrimProc(const GrPrimitiveProcessor&, GrGLSLExpr4* outputColor, GrGLSLExpr4* outputCoverage); - void emitAndInstallFragProcs(int procOffset, int numProcs, GrGLSLExpr4* inOut); + void emitAndInstallFragProcs(GrGLSLExpr4* colorInOut, GrGLSLExpr4* coverageInOut); void emitAndInstallFragProc(const GrFragmentProcessor&, int index, + int transformedCoordVarsIdx, const GrGLSLExpr4& input, GrGLSLExpr4* output); void emitAndInstallXferProc(const GrXferProcessor&, @@ -167,11 +168,10 @@ private: void verify(const GrFragmentProcessor&); #endif - GrGLSLPrimitiveProcessor::TransformsIn fCoordTransforms; - GrGLSLPrimitiveProcessor::TransformsOut fOutCoords; - int fNumVertexSamplers; - int fNumGeometrySamplers; - int fNumFragmentSamplers; + int fNumVertexSamplers; + int fNumGeometrySamplers; + int fNumFragmentSamplers; + SkSTArray<4, GrShaderVar> fTransformedCoordVars; }; #endif -- cgit v1.2.3