diff options
author | bsalomon <bsalomon@google.com> | 2016-09-26 06:55:02 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-09-26 06:55:02 -0700 |
commit | b58a2b4919aa67ab5bab1d497f26671d704654b4 (patch) | |
tree | bc1f99168fb99c090d0c753d6c8ecbbe0e654772 /src | |
parent | 94d7872ab3b0a32675b8e826637665fd3ada5b35 (diff) |
Stop aggregating texture/buffer access objects in GrFragmentProcessor parents.
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2349243002
Review-Url: https://codereview.chromium.org/2365943003
Diffstat (limited to 'src')
-rw-r--r-- | src/effects/gradients/SkGradientShader.cpp | 2 | ||||
-rw-r--r-- | src/effects/gradients/SkGradientShaderPriv.h | 2 | ||||
-rw-r--r-- | src/gpu/GrFragmentProcessor.cpp | 35 | ||||
-rw-r--r-- | src/gpu/GrPipeline.cpp | 11 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 22 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentProcessor.cpp | 75 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentProcessor.h | 75 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLProgramBuilder.cpp | 19 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.cpp | 5 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipelineState.cpp | 16 |
10 files changed, 114 insertions, 148 deletions
diff --git a/src/effects/gradients/SkGradientShader.cpp b/src/effects/gradients/SkGradientShader.cpp index d625d8eb13..31ff9ab877 100644 --- a/src/effects/gradients/SkGradientShader.cpp +++ b/src/effects/gradients/SkGradientShader.cpp @@ -1248,7 +1248,7 @@ void GrGradientEffect::GLSLProcessor::emitColor(GrGLSLFPFragmentBuilder* fragBui const char* gradientTValue, const char* outputColor, const char* inputColor, - const SamplerHandle* texSamplers) { + const TextureSamplers& texSamplers) { switch (ge.getColorType()) { #if GR_GL_USE_ACCURATE_HARD_STOP_GRADIENTS case kHardStopCentered_ColorType: { diff --git a/src/effects/gradients/SkGradientShaderPriv.h b/src/effects/gradients/SkGradientShaderPriv.h index d8d50e8fa0..4e6a325c8a 100644 --- a/src/effects/gradients/SkGradientShaderPriv.h +++ b/src/effects/gradients/SkGradientShaderPriv.h @@ -470,7 +470,7 @@ protected: const char* gradientTValue, const char* outputColor, const char* inputColor, - const SamplerHandle* texSamplers); + const TextureSamplers&); private: enum { diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp index 3dfe25ea28..72336587c4 100644 --- a/src/gpu/GrFragmentProcessor.cpp +++ b/src/gpu/GrFragmentProcessor.cpp @@ -57,40 +57,20 @@ GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const { } void GrFragmentProcessor::addTextureAccess(const GrTextureAccess* textureAccess) { - // Can't add texture accesses after registering any children since their texture accesses have - // already been bubbled up into our fTextureAccesses array - SkASSERT(fChildProcessors.empty()); - INHERITED::addTextureAccess(textureAccess); - fNumTexturesExclChildren++; } void GrFragmentProcessor::addBufferAccess(const GrBufferAccess* bufferAccess) { - // Can't add buffer accesses after registering any children since their buffer accesses have - // already been bubbled up into our fBufferAccesses array - SkASSERT(fChildProcessors.empty()); - INHERITED::addBufferAccess(bufferAccess); - fNumBuffersExclChildren++; } void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { - // Can't add transforms after registering any children since their transforms have already been - // bubbled up into our fCoordTransforms array - SkASSERT(fChildProcessors.empty()); - fCoordTransforms.push_back(transform); fUsesLocalCoords = fUsesLocalCoords || transform->sourceCoords() == kLocal_GrCoordSet; SkDEBUGCODE(transform->setInProcessor();) } int GrFragmentProcessor::registerChildProcessor(sk_sp<GrFragmentProcessor> child) { - // Append the child's textures array to our textures array - if (!child->fTextureAccesses.empty()) { - fTextureAccesses.push_back_n(child->fTextureAccesses.count(), - child->fTextureAccesses.begin()); - } - this->combineRequiredFeatures(*child); if (child->usesLocalCoords()) { @@ -424,18 +404,3 @@ const GrFragmentProcessor* GrFragmentProcessor::Iter::next() { return back; } -////////////////////////////////////////////////////////////////////////////// - -const GrCoordTransform* GrFragmentProcessor::CoordTransformIter::next() { - if (!fCurrFP) { - return nullptr; - } - while (fCTIdx == fCurrFP->numCoordTransforms()) { - fCTIdx = 0; - fCurrFP = fFPIter.next(); - if (!fCurrFP) { - return nullptr; - } - } - return &fCurrFP->coordTransform(fCTIdx++); -} diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index f7ad882172..d9ebcf85f9 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -176,15 +176,10 @@ GrPipeline* GrPipeline::CreateAt(void* memory, const CreateArgs& args, } static void add_dependencies_for_processor(const GrFragmentProcessor* proc, GrRenderTarget* rt) { - for (int i = 0; i < proc->numChildProcessors(); ++i) { - // need to recurse - add_dependencies_for_processor(&proc->childProcessor(i), rt); - } - - for (int i = 0; i < proc->numTextures(); ++i) { - GrTexture* texture = proc->textureAccess(i).getTexture(); + GrFragmentProcessor::TextureAccessIter iter(proc); + while (const GrTextureAccess* access = iter.next()) { SkASSERT(rt->getLastDrawTarget()); - rt->getLastDrawTarget()->addDependency(texture); + rt->getLastDrawTarget()->addDependency(access->getTexture()); } } diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index f34fce43b4..dd73d01dc1 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -88,10 +88,9 @@ void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { this->generateMipmaps(primProc, pipeline.getAllowSRGBInputs()); - int numProcessors = fFragmentProcessors.count(); - for (int i = 0; i < numProcessors; ++i) { - const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); - this->generateMipmaps(processor, pipeline.getAllowSRGBInputs()); + GrFragmentProcessor::Iter iter(pipeline); + while (const GrFragmentProcessor* fp = iter.next()) { + this->generateMipmaps(*fp, pipeline.getAllowSRGBInputs()); } if (primProc.getPixelLocalStorageState() != @@ -104,12 +103,17 @@ void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, int* nextSamplerIdx) { - int numProcessors = fFragmentProcessors.count(); - for (int i = 0; i < numProcessors; ++i) { - const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); - fFragmentProcessors[i]->setData(fProgramDataManager, processor); - this->bindTextures(processor, pipeline.getAllowSRGBInputs(), nextSamplerIdx); + GrFragmentProcessor::Iter iter(pipeline); + GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(), + fFragmentProcessors.count()); + const GrFragmentProcessor* fp = iter.next(); + GrGLSLFragmentProcessor* glslFP = glslIter.next(); + while (fp && glslFP) { + glslFP->setData(fProgramDataManager, *fp); + this->bindTextures(*fp, pipeline.getAllowSRGBInputs(), nextSamplerIdx); + fp = iter.next(), glslFP = glslIter.next(); } + SkASSERT(!fp && !glslFP); } diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp index 82a07ca39d..5ae7fee7db 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.cpp +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.cpp @@ -42,58 +42,13 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu const GrFragmentProcessor& childProc = args.fFp.childProcessor(childIndex); - /* - * 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 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] - * / \ - * / \ - * (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 D, we want the - * 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 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 firstTextureAt = args.fFp.numTexturesExclChildren(); - int firstBufferAt = args.fFp.numBuffersExclChildren(); - for (int i = 0; i < childIndex; ++i) { - firstTextureAt += args.fFp.childProcessor(i).numTextures(); - firstBufferAt += args.fFp.childProcessor(i).numBuffers(); - } - const SamplerHandle* childTexSamplers = nullptr; - const SamplerHandle* childBufferSamplers = nullptr; - if (childProc.numTextures() > 0) { - childTexSamplers = &args.fTexSamplers[firstTextureAt]; - } - if (childProc.numBuffers() > 0) { - childBufferSamplers = &args.fBufferSamplers[firstBufferAt]; - } - // emit the code for the child in its own scope 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); + TransformedCoordVars coordVars = args.fTransformedCoords.childInputs(childIndex); + TextureSamplers textureSamplers = args.fTexSamplers.childInputs(childIndex); + BufferSamplers bufferSamplers = args.fBufferSamplers.childInputs(childIndex); EmitArgs childArgs(fragBuilder, args.fUniformHandler, args.fGLSLCaps, @@ -101,8 +56,8 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu outputColor, inputColor, coordVars, - childTexSamplers, - childBufferSamplers, + textureSamplers, + bufferSamplers, args.fGpImplementsDistanceVector); this->childProcessor(childIndex)->emitCode(childArgs); fragBuilder->codeAppend("}\n"); @@ -112,16 +67,14 @@ void GrGLSLFragmentProcessor::internalEmitChild(int childIndex, const char* inpu ////////////////////////////////////////////////////////////////////////////// -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(); +GrGLSLFragmentProcessor* GrGLSLFragmentProcessor::Iter::next() { + if (fFPStack.empty()) { + return nullptr; + } + GrGLSLFragmentProcessor* back = fFPStack.back(); + fFPStack.pop_back(); + for (int i = back->numChildProcessors() - 1; i >= 0; --i) { + fFPStack.push_back(back->childProcessor(i)); } + return back; } diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h index 9889bcc9c6..d2f00f8b33 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.h +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h @@ -33,30 +33,49 @@ public: typedef GrGLSLProgramDataManager::UniformHandle UniformHandle; typedef GrGLSLProgramDataManager::UniformHandle SamplerHandle; +private: /** - * 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. + * This class allows the shader builder to provide each GrGLSLFragmentProcesor with an array of + * generated variables where each generated variable corresponds to an element of an array on + * the GrFragmentProcessor that generated the GLSLFP. For example, this is used to provide a + * variable holding transformed coords for each GrCoordTransform owned by the FP. */ - class TransformedCoordVars { + template <typename T, typename FPBASE, int (FPBASE::*COUNT)() const> + class BuilderInputProvider { public: - TransformedCoordVars(const GrFragmentProcessor* fp, const GrShaderVar* vars) - : fFP(fp) - , fTransformedVars(vars) {} + BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} - const GrShaderVar& operator[] (int i) const { - SkASSERT(i >= 0 && i < fFP->numCoordTransforms()); - return fTransformedVars[i]; + const T& operator[] (int i) const { + SkASSERT(i >= 0 && i < (fFP->*COUNT)()); + return fTs[i]; } - TransformedCoordVars childTransforms(int childIdx) const; + BuilderInputProvider childInputs(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 BuilderInputProvider(child, fTs + numToSkip); + } + numToSkip += (fp->*COUNT)(); + } + } private: const GrFragmentProcessor* fFP; - const GrShaderVar* fTransformedVars; + const T* fTs; }; +public: + using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor, + &GrFragmentProcessor::numCoordTransforms>; + using TextureSamplers = BuilderInputProvider<SamplerHandle, GrProcessor, + &GrProcessor::numTextures>; + using BufferSamplers = BuilderInputProvider<SamplerHandle, GrProcessor, + &GrProcessor::numBuffers>; + /** 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. @@ -90,8 +109,8 @@ public: const char* outputColor, const char* inputColor, const TransformedCoordVars& transformedCoordVars, - const SamplerHandle* texSamplers, - const SamplerHandle* bufferSamplers, + const TextureSamplers& textureSamplers, + const BufferSamplers& bufferSamplers, bool gpImplementsDistanceVector) : fFragBuilder(fragBuilder) , fUniformHandler(uniformHandler) @@ -100,7 +119,7 @@ public: , fOutputColor(outputColor) , fInputColor(inputColor) , fTransformedCoords(transformedCoordVars) - , fTexSamplers(texSamplers) + , fTexSamplers(textureSamplers) , fBufferSamplers(bufferSamplers) , fGpImplementsDistanceVector(gpImplementsDistanceVector) {} GrGLSLFPFragmentBuilder* fFragBuilder; @@ -110,8 +129,8 @@ public: const char* fOutputColor; const char* fInputColor; const TransformedCoordVars& fTransformedCoords; - const SamplerHandle* fTexSamplers; - const SamplerHandle* fBufferSamplers; + const TextureSamplers& fTexSamplers; + const BufferSamplers& fBufferSamplers; bool fGpImplementsDistanceVector; }; @@ -123,7 +142,7 @@ public: int numChildProcessors() const { return fChildProcessors.count(); } - GrGLSLFragmentProcessor* childProcessor(int index) const { + GrGLSLFragmentProcessor* childProcessor(int index) { return fChildProcessors[index]; } @@ -141,6 +160,24 @@ public: /** Variation that uses the parent's output color variable to hold the child's output.*/ void emitChild(int childIndex, const char* inputColor, EmitArgs& parentArgs); + /** + * Pre-order traversal of a GLSLFP hierarchy, or of multiple trees with roots in an array of + * GLSLFPS. This agrees with the traversal order of GrFragmentProcessor::Iter + */ + class Iter : public SkNoncopyable { + public: + explicit Iter(GrGLSLFragmentProcessor* fp) { fFPStack.push_back(fp); } + explicit Iter(GrGLSLFragmentProcessor* fps[], int cnt) { + for (int i = cnt - 1; i >= 0; --i) { + fFPStack.push_back(fps[i]); + } + } + GrGLSLFragmentProcessor* next(); + + private: + SkSTArray<4, GrGLSLFragmentProcessor*, true> fFPStack; + }; + protected: /** A GrGLSLFragmentProcessor instance can be reused with any GrFragmentProcessor that produces the same stage key; this function reads data from a GrFragmentProcessor and uploads any diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index 29470c4e2b..abfeafda0c 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -158,12 +158,17 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance(); - SkSTArray<4, SamplerHandle> texSamplers(fp.numTextures()); - SkSTArray<2, SamplerHandle> bufferSamplers(fp.numBuffers()); - this->emitSamplers(fp, &texSamplers, &bufferSamplers); + SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextures()); + SkSTArray<2, SamplerHandle> bufferSamplerArray(fp.numBuffers()); + GrFragmentProcessor::Iter iter(&fp); + while (const GrFragmentProcessor* subFP = iter.next()) { + this->emitSamplers(*subFP, &textureSamplerArray, &bufferSamplerArray); + } const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx; GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars); + GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin()); + GrGLSLFragmentProcessor::BufferSamplers bufferSamplers(&fp, bufferSamplerArray.begin()); GrGLSLFragmentProcessor::EmitArgs args(&fFS, this->uniformHandler(), this->glslCaps(), @@ -171,8 +176,8 @@ void GrGLSLProgramBuilder::emitAndInstallFragProc(const GrFragmentProcessor& fp, output->c_str(), input.isOnes() ? nullptr : input.c_str(), coords, - texSamplers.begin(), - bufferSamplers.begin(), + textureSamplers, + bufferSamplers, this->primitiveProcessor().implementsDistanceVector()); fragProc->emitCode(args); @@ -248,7 +253,7 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor, 1 << GrGLSLShaderBuilder::kExternalTexture_GLSLPrivateFeature, externalFeatureString); } - name.printf("TextureSampler%d", t); + name.printf("TextureSampler_%d", outTexSamplers->count()); this->emitSampler(samplerType, access.getTexture()->config(), name.c_str(), access.getVisibility(), outTexSamplers); } @@ -259,7 +264,7 @@ void GrGLSLProgramBuilder::emitSamplers(const GrProcessor& processor, for (int b = 0; b < numBuffers; ++b) { const GrBufferAccess& access = processor.bufferAccess(b); - name.printf("BufferSampler%d", b); + name.printf("BufferSampler_%d", outBufferSamplers->count()); this->emitSampler(kTextureBufferSampler_GrSLType, access.texelConfig(), name.c_str(), access.visibility(), outBufferSamplers); texelBufferVisibility |= access.visibility(); diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index a5840699b8..419e1b9f2c 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -395,8 +395,9 @@ void GrVkGpuCommandBuffer::onDraw(const GrPipeline& pipeline, SkASSERT(renderPass); prepare_sampled_images(primProc, fGpu); - for (int i = 0; i < pipeline.numFragmentProcessors(); ++i) { - prepare_sampled_images(pipeline.getFragmentProcessor(i), fGpu); + GrFragmentProcessor::Iter iter(pipeline); + while (const GrFragmentProcessor* fp = iter.next()) { + prepare_sampled_images(*fp, fGpu); } prepare_sampled_images(pipeline.getXferProcessor(), fGpu); diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp index 73ff62ed98..48724c07ba 100644 --- a/src/gpu/vk/GrVkPipelineState.cpp +++ b/src/gpu/vk/GrVkPipelineState.cpp @@ -198,11 +198,17 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, GrFragmentProcessor::CoordTransformIter(pipeline)); append_texture_bindings(primProc, &textureBindings); - for (int i = 0; i < fFragmentProcessors.count(); ++i) { - const GrFragmentProcessor& processor = pipeline.getFragmentProcessor(i); - fFragmentProcessors[i]->setData(fDataManager, processor); - append_texture_bindings(processor, &textureBindings); - } + GrFragmentProcessor::Iter iter(pipeline); + GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.begin(), + fFragmentProcessors.count()); + const GrFragmentProcessor* fp = iter.next(); + GrGLSLFragmentProcessor* glslFP = glslIter.next(); + while (fp && glslFP) { + glslFP->setData(fDataManager, *fp); + append_texture_bindings(*fp, &textureBindings); + fp = iter.next(), glslFP = glslIter.next(); + } + SkASSERT(!fp && !glslFP); fXferProcessor->setData(fDataManager, pipeline.getXferProcessor()); append_texture_bindings(pipeline.getXferProcessor(), &textureBindings); |