From e782f8472f61a5a553c57fef788ad4405844887b Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Tue, 31 Jul 2018 13:53:11 -0400 Subject: Remove GrResourceIOProcessor. Fold its functionality into GrPrimitiveProcessor and GrFragmentProcessor. Make each have its own TextureSampler nested class. Currently the only difference is that fragment processors lose the ability to inject their samplers into the vertex shader. However, this facilitates refactoring GrPrimitiveProcessor's TextureSampler class such that the textures are specified separately from the TextureSampler. Bug: skia: Change-Id: I1e590187e7a6ae79ee3147155d397fcdcf5e4619 Reviewed-on: https://skia-review.googlesource.com/142814 Commit-Queue: Brian Salomon Reviewed-by: Robert Phillips --- include/private/GrSurfaceProxyRef.h | 28 ++--- .../imagefilters/SkDisplacementMapEffect.cpp | 2 +- src/gpu/GrFragmentProcessor.cpp | 63 ++++++++++- src/gpu/GrFragmentProcessor.h | 120 +++++++++++++++++--- src/gpu/GrPipeline.cpp | 2 +- src/gpu/GrPrimitiveProcessor.cpp | 68 +++++++++++- src/gpu/GrPrimitiveProcessor.h | 101 ++++++++++++++++- src/gpu/GrProcessor.cpp | 77 ------------- src/gpu/GrProcessor.h | 122 --------------------- src/gpu/GrProcessorSet.h | 2 +- src/gpu/GrProgramDesc.cpp | 59 ++++++++-- src/gpu/ccpr/GrCCClipProcessor.cpp | 2 +- src/gpu/gl/GrGLProgram.cpp | 60 +++++----- src/gpu/gl/GrGLProgram.h | 9 +- src/gpu/glsl/GrGLSLFragmentProcessor.h | 10 +- src/gpu/glsl/GrGLSLProgramBuilder.cpp | 45 ++++---- src/gpu/glsl/GrGLSLProgramBuilder.h | 2 - src/gpu/vk/GrVkGpuCommandBuffer.cpp | 54 ++++----- src/gpu/vk/GrVkPipelineState.cpp | 53 ++++----- src/gpu/vk/GrVkPipelineState.h | 9 +- tests/LazyProxyTest.cpp | 2 +- 21 files changed, 501 insertions(+), 389 deletions(-) diff --git a/include/private/GrSurfaceProxyRef.h b/include/private/GrSurfaceProxyRef.h index 38d5827614..fb2ed3746a 100644 --- a/include/private/GrSurfaceProxyRef.h +++ b/include/private/GrSurfaceProxyRef.h @@ -15,7 +15,17 @@ class GrSurfaceProxy; class GrSurfaceProxyRef : SkNoncopyable { public: - virtual ~GrSurfaceProxyRef(); + GrSurfaceProxyRef(); + + /** ioType expresses what type of IO operations will be marked as + pending on the resource when markPendingIO is called. */ + GrSurfaceProxyRef(sk_sp, GrIOType); + + ~GrSurfaceProxyRef(); + + /** ioType expresses what type of IO operations will be marked as + pending on the resource when markPendingIO is called. */ + void setProxy(sk_sp, GrIOType); GrSurfaceProxy* get() const { return fProxy; } @@ -30,18 +40,6 @@ public: is called. */ void reset(); -protected: - GrSurfaceProxyRef(); - - /** ioType expresses what type of IO operations will be marked as - pending on the resource when markPendingIO is called. */ - GrSurfaceProxyRef(sk_sp, GrIOType); - - /** ioType expresses what type of IO operations will be marked as - pending on the resource when markPendingIO is called. */ - void setProxy(sk_sp, GrIOType); - -private: /** Called by owning GrProgramElement when the program element is first scheduled for execution. It can only be called once. */ void markPendingIO() const; @@ -58,9 +56,7 @@ private: called. */ void pendingIOComplete() const; - friend class GrResourceIOProcessor; - friend class GrOpList; // for setProxy - +private: GrSurfaceProxy* fProxy; mutable bool fOwnRef; mutable bool fPendingIO; diff --git a/src/effects/imagefilters/SkDisplacementMapEffect.cpp b/src/effects/imagefilters/SkDisplacementMapEffect.cpp index 2ab8c5e051..356e82ed09 100644 --- a/src/effects/imagefilters/SkDisplacementMapEffect.cpp +++ b/src/effects/imagefilters/SkDisplacementMapEffect.cpp @@ -546,7 +546,7 @@ void GrGLDisplacementMapEffect::emitCode(EmitArgs& args) { GrGLSLFPFragmentBuilder* fragBuilder = args.fFragBuilder; fragBuilder->codeAppendf("\t\thalf4 %s = ", dColor); fragBuilder->appendTextureLookup(args.fTexSamplers[0], args.fTransformedCoords[0].c_str(), - args.fTransformedCoords[0].getType()); + args.fTransformedCoords[0].getType()); fragBuilder->codeAppend(";\n"); // Unpremultiply the displacement diff --git a/src/gpu/GrFragmentProcessor.cpp b/src/gpu/GrFragmentProcessor.cpp index 63dc39c36b..081aff31f8 100644 --- a/src/gpu/GrFragmentProcessor.cpp +++ b/src/gpu/GrFragmentProcessor.cpp @@ -19,10 +19,17 @@ #include "glsl/GrGLSLUniformHandler.h" bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const { - if (this->classID() != that.classID() || - !this->hasSameSamplers(that)) { + if (this->classID() != that.classID()) { return false; } + if (this->numTextureSamplers() != that.numTextureSamplers()) { + return false; + } + for (int i = 0; i < this->numTextureSamplers(); ++i) { + if (this->textureSampler(i) != that.textureSampler(i)) { + return false; + } + } if (!this->hasSameTransforms(that)) { return false; } @@ -40,6 +47,13 @@ bool GrFragmentProcessor::isEqual(const GrFragmentProcessor& that) const { return true; } +void GrFragmentProcessor::visitProxies(const std::function& func) { + GrFragmentProcessor::TextureAccessIter iter(this); + while (const TextureSampler* sampler = iter.next()) { + func(sampler->proxy()); + } +} + GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const { GrGLSLFragmentProcessor* glFragProc = this->onCreateGLSLInstance(); glFragProc->fChildProcessors.push_back_n(fChildProcessors.count()); @@ -49,6 +63,11 @@ GrGLSLFragmentProcessor* GrFragmentProcessor::createGLSLInstance() const { return glFragProc; } +const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::textureSampler(int i) const { + SkASSERT(i >= 0 && i < fTextureSamplerCnt); + return this->onTextureSampler(i); +} + void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { fCoordTransforms.push_back(transform); fFlags |= kUsesLocalCoords_Flag; @@ -56,8 +75,10 @@ void GrFragmentProcessor::addCoordTransform(const GrCoordTransform* transform) { } bool GrFragmentProcessor::instantiate(GrResourceProvider* resourceProvider) const { - if (!INHERITED::instantiate(resourceProvider)) { - return false; + for (int i = 0; i < fTextureSamplerCnt; ++i) { + if (!this->textureSampler(i).instantiate(resourceProvider)) { + return false; + } } for (int i = 0; i < this->numChildProcessors(); ++i) { @@ -70,8 +91,11 @@ bool GrFragmentProcessor::instantiate(GrResourceProvider* resourceProvider) cons } void GrFragmentProcessor::markPendingExecution() const { - INHERITED::addPendingIOs(); - INHERITED::removeRefs(); + for (int i = 0; i < fTextureSamplerCnt; ++i) { + auto* proxy = this->textureSampler(i).programProxy(); + proxy->markPendingIO(); + proxy->removeRef(); + } for (int i = 0; i < this->numChildProcessors(); ++i) { this->childProcessor(i).markPendingExecution(); } @@ -499,3 +523,30 @@ const GrFragmentProcessor* GrFragmentProcessor::Iter::next() { return back; } +/////////////////////////////////////////////////////////////////////////////////////////////////// + +GrFragmentProcessor::TextureSampler::TextureSampler(sk_sp proxy, + const GrSamplerState& samplerState) { + this->reset(std::move(proxy), samplerState); +} + +GrFragmentProcessor::TextureSampler::TextureSampler(sk_sp proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY) { + this->reset(std::move(proxy), filterMode, wrapXAndY); +} + +void GrFragmentProcessor::TextureSampler::reset(sk_sp proxy, + const GrSamplerState& samplerState) { + fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); + fSamplerState = samplerState; + fSamplerState.setFilterMode(SkTMin(samplerState.filter(), this->proxy()->highestFilterMode())); +} + +void GrFragmentProcessor::TextureSampler::reset(sk_sp proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY) { + fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); + filterMode = SkTMin(filterMode, this->proxy()->highestFilterMode()); + fSamplerState = GrSamplerState(wrapXAndY, filterMode); +} diff --git a/src/gpu/GrFragmentProcessor.h b/src/gpu/GrFragmentProcessor.h index b875c7919f..8a35c57da9 100644 --- a/src/gpu/GrFragmentProcessor.h +++ b/src/gpu/GrFragmentProcessor.h @@ -24,8 +24,10 @@ class GrSwizzle; GrCoordTransforms to receive a transformation of the local coordinates that map from local space to the fragment being processed. */ -class GrFragmentProcessor : public GrResourceIOProcessor { +class GrFragmentProcessor : public GrProcessor { public: + class TextureSampler; + /** * In many instances (e.g. SkShader::asFragmentProcessor() implementations) it is desirable to * only consider the input color's alpha. However, there is a competing desire to have reusable @@ -115,6 +117,9 @@ public: } } + int numTextureSamplers() const { return fTextureSamplerCnt; } + const TextureSampler& textureSampler(int i) const; + int numCoordTransforms() const { return fCoordTransforms.count(); } /** Returns the coordinate transformation at index. index must be valid according to @@ -204,9 +209,8 @@ public: * owned by the forest of GrFragmentProcessors in a GrPipeline. FPs are visited in the same * order as Iter and each of an FP's Ts are visited in order. */ - template + template class FPItemIter : public SkNoncopyable { public: explicit FPItemIter(const GrFragmentProcessor* fp) @@ -243,21 +247,14 @@ public: }; using CoordTransformIter = FPItemIter; using TextureAccessIter = FPItemIter; - - void visitProxies(const std::function& func) { - GrFragmentProcessor::TextureAccessIter iter(this); - while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) { - func(sampler->proxy()); - } - } + &GrFragmentProcessor::numTextureSamplers, + &GrFragmentProcessor::textureSampler>; + + void visitProxies(const std::function& func); protected: enum OptimizationFlags : uint32_t { @@ -337,6 +334,22 @@ protected: */ int registerChildProcessor(std::unique_ptr child); + void setTextureSamplerCnt(int cnt) { + SkASSERT(cnt >= 0); + fTextureSamplerCnt = cnt; + } + + /** + * Helper for implementing onTextureSampler(). E.g.: + * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler); + */ + template + static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0, + const Args&... samps) { + return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...); + } + inline static const TextureSampler& IthTextureSampler(int i); + private: virtual GrColor4f constantOutputForConstantInput(GrColor4f /* inputColor */) const { SK_ABORT("Subclass must override this if advertising this optimization."); @@ -359,6 +372,8 @@ private: */ virtual bool onIsEqual(const GrFragmentProcessor&) const = 0; + virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); } + bool hasSameTransforms(const GrFragmentProcessor&) const; enum PrivateFlags { @@ -368,13 +383,86 @@ private: mutable uint32_t fFlags = 0; + int fTextureSamplerCnt = 0; + SkSTArray<4, const GrCoordTransform*, true> fCoordTransforms; SkSTArray<1, std::unique_ptr, true> fChildProcessors; - typedef GrResourceIOProcessor INHERITED; + typedef GrProcessor INHERITED; }; +/** + * Used to represent a texture that is required by a GrFragmentProcessor. It holds a GrTextureProxy + * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to + * account for texture origin. + */ +class GrFragmentProcessor::TextureSampler { +public: + TextureSampler() = default; + + /** + * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy + * always takes a new ref on the texture proxy as the new fragment processor will not yet be + * in pending execution state. + */ + explicit TextureSampler(const TextureSampler& that) + : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType()) + , fSamplerState(that.fSamplerState) {} + + TextureSampler(sk_sp, const GrSamplerState&); + + explicit TextureSampler(sk_sp, + GrSamplerState::Filter = GrSamplerState::Filter::kNearest, + GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp); + + TextureSampler& operator=(const TextureSampler&) = delete; + + void reset(sk_sp, const GrSamplerState&); + void reset(sk_sp, + GrSamplerState::Filter = GrSamplerState::Filter::kNearest, + GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp); + + bool operator==(const TextureSampler& that) const { + return this->proxy()->underlyingUniqueID() == that.proxy()->underlyingUniqueID() && + fSamplerState == that.fSamplerState; + } + + bool operator!=(const TextureSampler& other) const { return !(*this == other); } + + // 'instantiate' should only ever be called at flush time. + bool instantiate(GrResourceProvider* resourceProvider) const { + return SkToBool(fProxyRef.get()->instantiate(resourceProvider)); + } + + // 'peekTexture' should only ever be called after a successful 'instantiate' call + GrTexture* peekTexture() const { + SkASSERT(fProxyRef.get()->priv().peekTexture()); + return fProxyRef.get()->priv().peekTexture(); + } + + GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); } + const GrSamplerState& samplerState() const { return fSamplerState; } + + bool isInitialized() const { return SkToBool(fProxyRef.get()); } + /** + * For internal use by GrFragmentProcessor. + */ + const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; } + +private: + GrSurfaceProxyRef fProxyRef; + GrSamplerState fSamplerState; +}; + +////////////////////////////////////////////////////////////////////////////// + +const GrFragmentProcessor::TextureSampler& GrFragmentProcessor::IthTextureSampler(int i) { + SK_ABORT("Illegal texture sampler index"); + static const TextureSampler kBogus; + return kBogus; +} + GR_MAKE_BITFIELD_OPS(GrFragmentProcessor::OptimizationFlags) #endif diff --git a/src/gpu/GrPipeline.cpp b/src/gpu/GrPipeline.cpp index 6608d7c7d2..50545644a4 100644 --- a/src/gpu/GrPipeline.cpp +++ b/src/gpu/GrPipeline.cpp @@ -80,7 +80,7 @@ GrPipeline::GrPipeline(const InitArgs& args, void GrPipeline::addDependenciesTo(GrOpList* opList, const GrCaps& caps) const { for (int i = 0; i < fFragmentProcessors.count(); ++i) { GrFragmentProcessor::TextureAccessIter iter(fFragmentProcessors[i].get()); - while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) { + while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) { opList->addDependency(sampler->proxy(), caps); } } diff --git a/src/gpu/GrPrimitiveProcessor.cpp b/src/gpu/GrPrimitiveProcessor.cpp index db79fb1052..10b13370f4 100644 --- a/src/gpu/GrPrimitiveProcessor.cpp +++ b/src/gpu/GrPrimitiveProcessor.cpp @@ -17,7 +17,12 @@ enum MatrixType { kGeneral_MatrixType = 1, }; -GrPrimitiveProcessor::GrPrimitiveProcessor(ClassID classID) : GrResourceIOProcessor(classID) {} +GrPrimitiveProcessor::GrPrimitiveProcessor(ClassID classID) : GrProcessor(classID) {} + +const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::textureSampler(int i) const { + SkASSERT(i >= 0 && i < this->numTextureSamplers()); + return this->onTextureSampler(i); +} const GrPrimitiveProcessor::Attribute& GrPrimitiveProcessor::vertexAttribute(int i) const { SkASSERT(i >= 0 && i < this->numVertexAttributes()); @@ -69,6 +74,33 @@ size_t GrPrimitiveProcessor::debugOnly_instanceAttributeOffset(int i) const { } #endif +void GrPrimitiveProcessor::addPendingIOs() const { + for (int i = 0; i < fTextureSamplerCnt; ++i) { + this->textureSampler(i).programProxy()->markPendingIO(); + } +} + +void GrPrimitiveProcessor::removeRefs() const { + for (int i = 0; i < fTextureSamplerCnt; ++i) { + this->textureSampler(i).programProxy()->removeRef(); + } +} + +void GrPrimitiveProcessor::pendingIOComplete() const { + for (int i = 0; i < fTextureSamplerCnt; ++i) { + this->textureSampler(i).programProxy()->pendingIOComplete(); + } +} + +bool GrPrimitiveProcessor::instantiate(GrResourceProvider* resourceProvider) const { + for (int i = 0; i < fTextureSamplerCnt; ++i) { + if (!this->textureSampler(i).instantiate(resourceProvider)) { + return false; + } + } + return true; +} + uint32_t GrPrimitiveProcessor::getTransformKey(const SkTArray& coords, int numCoords) const { @@ -87,3 +119,37 @@ GrPrimitiveProcessor::getTransformKey(const SkTArray proxy, + const GrSamplerState& samplerState, + GrShaderFlags visibility) { + this->reset(std::move(proxy), samplerState, visibility); +} + +GrPrimitiveProcessor::TextureSampler::TextureSampler(sk_sp proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY, + GrShaderFlags visibility) { + this->reset(std::move(proxy), filterMode, wrapXAndY, visibility); +} + +void GrPrimitiveProcessor::TextureSampler::reset(sk_sp proxy, + const GrSamplerState& samplerState, + GrShaderFlags visibility) { + fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); + fSamplerState = samplerState; + fSamplerState.setFilterMode(SkTMin(samplerState.filter(), this->proxy()->highestFilterMode())); + fVisibility = visibility; +} + +void GrPrimitiveProcessor::TextureSampler::reset(sk_sp proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY, + GrShaderFlags visibility) { + fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); + filterMode = SkTMin(filterMode, this->proxy()->highestFilterMode()); + fSamplerState = GrSamplerState(wrapXAndY, filterMode); + fVisibility = visibility; +} diff --git a/src/gpu/GrPrimitiveProcessor.h b/src/gpu/GrPrimitiveProcessor.h index cc24b64a87..d5d5d5f747 100644 --- a/src/gpu/GrPrimitiveProcessor.h +++ b/src/gpu/GrPrimitiveProcessor.h @@ -40,8 +40,10 @@ class GrGLSLPrimitiveProcessor; * GrPrimitiveProcessors must proivide seed color and coverage for the Ganesh color / coverage * pipelines, and they must provide some notion of equality */ -class GrPrimitiveProcessor : public GrResourceIOProcessor, public GrProgramElement { +class GrPrimitiveProcessor : public GrProcessor, public GrProgramElement { public: + class TextureSampler; + /** Describes a vertex or instance attribute. */ class Attribute { public: @@ -70,6 +72,8 @@ public: GrPrimitiveProcessor(ClassID); + int numTextureSamplers() const { return fTextureSamplerCnt; } + const TextureSampler& textureSampler(int index) const; int numVertexAttributes() const { return fVertexAttributeCnt; } const Attribute& vertexAttribute(int i) const; int numInstanceAttributes() const { return fInstanceAttributeCnt; } @@ -131,26 +135,111 @@ public: virtual float getSampleShading() const { return 0.0; } + bool instantiate(GrResourceProvider*) const; + protected: - void setVertexAttributeCnt(int cnt) { fVertexAttributeCnt = cnt; } - void setInstanceAttributeCnt(int cnt) { fInstanceAttributeCnt = cnt; } + void setVertexAttributeCnt(int cnt) { + SkASSERT(cnt >= 0); + fVertexAttributeCnt = cnt; + } + void setInstanceAttributeCnt(int cnt) { + SkASSERT(cnt >= 0); + fInstanceAttributeCnt = cnt; + } + void setTextureSamplerCnt(int cnt) { + SkASSERT(cnt >= 0); + fTextureSamplerCnt = cnt; + } + + /** + * Helper for implementing onTextureSampler(). E.g.: + * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler); + */ + template + static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0, + const Args&... samps) { + return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...); + } + inline static const TextureSampler& IthTextureSampler(int i); private: - void addPendingIOs() const override { GrResourceIOProcessor::addPendingIOs(); } - void removeRefs() const override { GrResourceIOProcessor::removeRefs(); } - void pendingIOComplete() const override { GrResourceIOProcessor::pendingIOComplete(); } + void addPendingIOs() const final; + void removeRefs() const final; + void pendingIOComplete() const final; void notifyRefCntIsZero() const final {} virtual const Attribute& onVertexAttribute(int) const = 0; virtual const Attribute& onInstanceAttribute(int) const = 0; + virtual const TextureSampler& onTextureSampler(int) const { return IthTextureSampler(0); } int fVertexAttributeCnt = 0; int fInstanceAttributeCnt = 0; + int fTextureSamplerCnt = 0; typedef GrProcessor INHERITED; }; ////////////////////////////////////////////////////////////////////////////// +/** + * Used to represent a texture that is required by a GrPrimitiveProcessor. It holds a GrTextureProxy + * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to + * account for texture origin. + */ +class GrPrimitiveProcessor::TextureSampler { +public: + TextureSampler() = default; + + TextureSampler(sk_sp, const GrSamplerState&, GrShaderFlags visibility); + + explicit TextureSampler(sk_sp, + GrSamplerState::Filter = GrSamplerState::Filter::kNearest, + GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp, + GrShaderFlags visibility = kFragment_GrShaderFlag); + + TextureSampler(const TextureSampler&) = delete; + TextureSampler& operator=(const TextureSampler&) = delete; + + void reset(sk_sp, const GrSamplerState&, + GrShaderFlags visibility = kFragment_GrShaderFlag); + void reset(sk_sp, + GrSamplerState::Filter = GrSamplerState::Filter::kNearest, + GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp, + GrShaderFlags visibility = kFragment_GrShaderFlag); + + bool instantiate(GrResourceProvider* resourceProvider) const { + return SkToBool(fProxyRef.get()->instantiate(resourceProvider)); + } + + // 'peekTexture' should only ever be called after a successful 'instantiate' call + GrTexture* peekTexture() const { + SkASSERT(fProxyRef.get()->priv().peekTexture()); + return fProxyRef.get()->priv().peekTexture(); + } + + GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); } + GrShaderFlags visibility() const { return fVisibility; } + const GrSamplerState& samplerState() const { return fSamplerState; } + + bool isInitialized() const { return SkToBool(fProxyRef.get()); } + /** + * For internal use by GrPrimitiveProcessor. + */ + const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; } + +private: + GrSurfaceProxyRef fProxyRef; + GrSamplerState fSamplerState; + GrShaderFlags fVisibility = kNone_GrShaderFlags; +}; + +const GrPrimitiveProcessor::TextureSampler& GrPrimitiveProcessor::IthTextureSampler(int i) { + SK_ABORT("Illegal texture sampler index"); + static const TextureSampler kBogus; + return kBogus; +} + +////////////////////////////////////////////////////////////////////////////// + /** * Returns the size of the attrib type in bytes. * This was moved from include/private/GrTypesPriv.h in service of Skia dependents that build diff --git a/src/gpu/GrProcessor.cpp b/src/gpu/GrProcessor.cpp index 43b4213dc1..aba8d9b4ae 100644 --- a/src/gpu/GrProcessor.cpp +++ b/src/gpu/GrProcessor.cpp @@ -125,80 +125,3 @@ void* GrProcessor::operator new(size_t size) { return MemoryPoolAccessor().pool( void GrProcessor::operator delete(void* target) { return MemoryPoolAccessor().pool()->release(target); } - -/////////////////////////////////////////////////////////////////////////////// - -void GrResourceIOProcessor::addPendingIOs() const { - for (int i = 0; i < fNumTextureSamplers; ++i) { - this->textureSampler(i).programProxy()->markPendingIO(); - } -} - -void GrResourceIOProcessor::removeRefs() const { - for (int i = 0; i < fNumTextureSamplers; ++i) { - this->textureSampler(i).programProxy()->removeRef(); - } -} - -void GrResourceIOProcessor::pendingIOComplete() const { - for (int i = 0; i < fNumTextureSamplers; ++i) { - this->textureSampler(i).programProxy()->pendingIOComplete(); - } -} - -bool GrResourceIOProcessor::instantiate(GrResourceProvider* resourceProvider) const { - for (int i = 0; i < fNumTextureSamplers; ++i) { - if (!this->textureSampler(i).instantiate(resourceProvider)) { - return false; - } - } - - return true; -} - -bool GrResourceIOProcessor::hasSameSamplers(const GrResourceIOProcessor& that) const { - if (this->numTextureSamplers() != that.numTextureSamplers()) { - return false; - } - for (int i = 0; i < this->numTextureSamplers(); ++i) { - if (this->textureSampler(i) != that.textureSampler(i)) { - return false; - } - } - return true; -} - -/////////////////////////////////////////////////////////////////////////////////////////////////// - -GrResourceIOProcessor::TextureSampler::TextureSampler() {} - -GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp proxy, - const GrSamplerState& samplerState) { - this->reset(std::move(proxy), samplerState); -} - -GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp proxy, - GrSamplerState::Filter filterMode, - GrSamplerState::WrapMode wrapXAndY, - GrShaderFlags visibility) { - this->reset(std::move(proxy), filterMode, wrapXAndY, visibility); -} - -void GrResourceIOProcessor::TextureSampler::reset(sk_sp proxy, - const GrSamplerState& samplerState, - GrShaderFlags visibility) { - fSamplerState = samplerState; - fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); - fSamplerState.setFilterMode(SkTMin(samplerState.filter(), this->proxy()->highestFilterMode())); - fVisibility = visibility; -} - -void GrResourceIOProcessor::TextureSampler::reset(sk_sp proxy, - GrSamplerState::Filter filterMode, - GrSamplerState::WrapMode wrapXAndY, - GrShaderFlags visibility) { - fProxyRef.setProxy(std::move(proxy), kRead_GrIOType); - filterMode = SkTMin(filterMode, this->proxy()->highestFilterMode()); - fSamplerState = GrSamplerState(wrapXAndY, filterMode); - fVisibility = visibility; -} diff --git a/src/gpu/GrProcessor.h b/src/gpu/GrProcessor.h index f4a1e1682b..1c0161a811 100644 --- a/src/gpu/GrProcessor.h +++ b/src/gpu/GrProcessor.h @@ -196,126 +196,4 @@ private: ClassID fClassID; }; -/** A GrProcessor with the ability to access textures, buffers, and image storages. */ -class GrResourceIOProcessor : public GrProcessor { -public: - class TextureSampler; - - int numTextureSamplers() const { return fNumTextureSamplers; } - - /** Gets a TextureSampler which is a combination of a GrTextureProxy and how it is sampled. - * index must be valid according to numTextureSamplers(). */ - const TextureSampler& textureSampler(int index) const { - SkASSERT(index >= 0 && index < fNumTextureSamplers); - return this->onTextureSampler(index); - } - - bool instantiate(GrResourceProvider* resourceProvider) const; - -protected: - template - static const TextureSampler& IthTextureSampler(int i, const TextureSampler& samp0, - const Args&... samps) { - return (0 == i) ? samp0 : IthTextureSampler(i - 1, samps...); - } - inline static const TextureSampler& IthTextureSampler(int i); - - GrResourceIOProcessor(ClassID classID) : INHERITED(classID) {} - - void setTextureSamplerCnt(int numTextureSamplers) { - SkASSERT(numTextureSamplers >= 0); - fNumTextureSamplers = numTextureSamplers; - } - - bool hasSameSamplers(const GrResourceIOProcessor&) const; - - // These methods can be used by derived classes that also derive from GrProgramElement. - void addPendingIOs() const; - void removeRefs() const; - void pendingIOComplete() const; - -private: - virtual const TextureSampler& onTextureSampler(int index) const { return IthTextureSampler(0); } - - int fNumTextureSamplers = 0; - typedef GrProcessor INHERITED; -}; - -/** - * Used to represent a texture that is required by a GrResourceIOProcessor. It holds a GrTexture - * along with an associated GrSamplerState. TextureSamplers don't perform any coord manipulation to - * account for texture origin. - */ -class GrResourceIOProcessor::TextureSampler { -public: - /** - * Must be initialized before adding to a GrProcessor's texture access list. - */ - TextureSampler(); - /** - * This copy constructor is used by GrFragmentProcessor::clone() implementations. The copy - * always takes a new ref on the texture proxy as the new fragment processor will not yet be - * in pending execution state. - */ - explicit TextureSampler(const TextureSampler& that) - : fProxyRef(sk_ref_sp(that.fProxyRef.get()), that.fProxyRef.ioType()) - , fSamplerState(that.fSamplerState) - , fVisibility(that.fVisibility) {} - - TextureSampler(sk_sp, const GrSamplerState&); - - explicit TextureSampler(sk_sp, - GrSamplerState::Filter = GrSamplerState::Filter::kNearest, - GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp, - GrShaderFlags visibility = kFragment_GrShaderFlag); - - TextureSampler& operator=(const TextureSampler&) = delete; - - void reset(sk_sp, const GrSamplerState&, - GrShaderFlags visibility = kFragment_GrShaderFlag); - void reset(sk_sp, - GrSamplerState::Filter = GrSamplerState::Filter::kNearest, - GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp, - GrShaderFlags visibility = kFragment_GrShaderFlag); - - bool operator==(const TextureSampler& that) const { - return this->proxy()->underlyingUniqueID() == that.proxy()->underlyingUniqueID() && - fSamplerState == that.fSamplerState && fVisibility == that.fVisibility; - } - - bool operator!=(const TextureSampler& other) const { return !(*this == other); } - - // 'instantiate' should only ever be called at flush time. - bool instantiate(GrResourceProvider* resourceProvider) const { - return SkToBool(fProxyRef.get()->instantiate(resourceProvider)); - } - - // 'peekTexture' should only ever be called after a successful 'instantiate' call - GrTexture* peekTexture() const { - SkASSERT(fProxyRef.get()->priv().peekTexture()); - return fProxyRef.get()->priv().peekTexture(); - } - - GrTextureProxy* proxy() const { return fProxyRef.get()->asTextureProxy(); } - GrShaderFlags visibility() const { return fVisibility; } - const GrSamplerState& samplerState() const { return fSamplerState; } - - bool isInitialized() const { return SkToBool(fProxyRef.get()); } - /** - * For internal use by GrProcessor. - */ - const GrSurfaceProxyRef* programProxy() const { return &fProxyRef; } - -private: - GrSurfaceProxyRef fProxyRef; - GrSamplerState fSamplerState; - GrShaderFlags fVisibility; -}; - -const GrResourceIOProcessor::TextureSampler& GrResourceIOProcessor::IthTextureSampler(int i) { - SK_ABORT("Illegal texture sampler index"); - static const TextureSampler kBogus; - return kBogus; -} - #endif diff --git a/src/gpu/GrProcessorSet.h b/src/gpu/GrProcessorSet.h index 05d0a59ab2..5dd1c4876e 100644 --- a/src/gpu/GrProcessorSet.h +++ b/src/gpu/GrProcessorSet.h @@ -155,7 +155,7 @@ public: void visitProxies(const std::function& func) const { for (int i = 0; i < this->numFragmentProcessors(); ++i) { GrFragmentProcessor::TextureAccessIter iter(this->fragmentProcessor(i)); - while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) { + while (const GrFragmentProcessor::TextureSampler* sampler = iter.next()) { func(sampler->proxy()); } } diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp index b0396f9c37..e99a947d80 100644 --- a/src/gpu/GrProgramDesc.cpp +++ b/src/gpu/GrProgramDesc.cpp @@ -49,21 +49,39 @@ static uint16_t sampler_key(GrTextureType textureType, GrPixelConfig config, (GrSLSamplerPrecision(config) << (8 + kSamplerOrImageTypeKeyBits))); } -static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourceIOProcessor& proc, - const GrShaderCaps& caps) { - int numTextureSamplers = proc.numTextureSamplers(); +static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrFragmentProcessor& fp, + const GrShaderCaps& caps) { + int numTextureSamplers = fp.numTextureSamplers(); // Need two bytes per key. int word32Count = (numTextureSamplers + 1) / 2; if (0 == word32Count) { return; } uint16_t* k16 = reinterpret_cast(b->add32n(word32Count)); - int j = 0; - for (int i = 0; i < numTextureSamplers; ++i, ++j) { - const GrResourceIOProcessor::TextureSampler& sampler = proc.textureSampler(i); + for (int i = 0; i < numTextureSamplers; ++i) { + const GrFragmentProcessor::TextureSampler& sampler = fp.textureSampler(i); const GrTexture* tex = sampler.peekTexture(); + k16[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps); + } + // zero the last 16 bits if the number of uniforms for samplers is odd. + if (numTextureSamplers & 0x1) { + k16[numTextureSamplers] = 0; + } +} - k16[j] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps); +static void add_sampler_keys(GrProcessorKeyBuilder* b, const GrPrimitiveProcessor& pp, + const GrShaderCaps& caps) { + int numTextureSamplers = pp.numTextureSamplers(); + // Need two bytes per key. + int word32Count = (numTextureSamplers + 1) / 2; + if (0 == word32Count) { + return; + } + uint16_t* k16 = reinterpret_cast(b->add32n(word32Count)); + for (int i = 0; i < numTextureSamplers; ++i) { + const GrPrimitiveProcessor::TextureSampler& sampler = pp.textureSampler(i); + const GrTexture* tex = sampler.peekTexture(); + k16[i] = sampler_key(tex->texturePriv().textureType(), tex->config(), caps); } // zero the last 16 bits if the number of uniforms for samplers is odd. if (numTextureSamplers & 0x1) { @@ -80,12 +98,33 @@ static void add_sampler_and_image_keys(GrProcessorKeyBuilder* b, const GrResourc * transforms, etc, for the space allotted in the meta-key. NOTE, both FPs and GPs share this * function because it is hairy, though FPs do not have attribs, and GPs do not have transforms */ -static bool gen_meta_key(const GrResourceIOProcessor& proc, +static bool gen_meta_key(const GrFragmentProcessor& fp, + const GrShaderCaps& shaderCaps, + uint32_t transformKey, + GrProcessorKeyBuilder* b) { + size_t processorKeySize = b->size(); + uint32_t classID = fp.classID(); + + // Currently we allow 16 bits for the class id and the overall processor key size. + static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)UINT16_MAX); + if ((processorKeySize | classID) & kMetaKeyInvalidMask) { + return false; + } + + add_sampler_keys(b, fp, shaderCaps); + + uint32_t* key = b->add32n(2); + key[0] = (classID << 16) | SkToU32(processorKeySize); + key[1] = transformKey; + return true; +} + +static bool gen_meta_key(const GrPrimitiveProcessor& pp, const GrShaderCaps& shaderCaps, uint32_t transformKey, GrProcessorKeyBuilder* b) { size_t processorKeySize = b->size(); - uint32_t classID = proc.classID(); + uint32_t classID = pp.classID(); // Currently we allow 16 bits for the class id and the overall processor key size. static const uint32_t kMetaKeyInvalidMask = ~((uint32_t)UINT16_MAX); @@ -93,7 +132,7 @@ static bool gen_meta_key(const GrResourceIOProcessor& proc, return false; } - add_sampler_and_image_keys(b, proc, shaderCaps); + add_sampler_keys(b, pp, shaderCaps); uint32_t* key = b->add32n(2); key[0] = (classID << 16) | SkToU32(processorKeySize); diff --git a/src/gpu/ccpr/GrCCClipProcessor.cpp b/src/gpu/ccpr/GrCCClipProcessor.cpp index 0c1f0e8459..864ac58596 100644 --- a/src/gpu/ccpr/GrCCClipProcessor.cpp +++ b/src/gpu/ccpr/GrCCClipProcessor.cpp @@ -21,7 +21,7 @@ GrCCClipProcessor::GrCCClipProcessor(const GrCCClipPath* clipPath, MustCheckBoun , fMustCheckBounds((bool)mustCheckBounds) , fOverrideFillType(overrideFillType) , fAtlasAccess(sk_ref_sp(fClipPath->atlasLazyProxy()), GrSamplerState::Filter::kNearest, - GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag) { + GrSamplerState::WrapMode::kClamp) { this->setTextureSamplerCnt(1); } diff --git a/src/gpu/gl/GrGLProgram.cpp b/src/gpu/gl/GrGLProgram.cpp index 52d53bde95..a392bc26f0 100644 --- a/src/gpu/gl/GrGLProgram.cpp +++ b/src/gpu/gl/GrGLProgram.cpp @@ -84,9 +84,13 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline int nextTexSamplerIdx = 0; fPrimitiveProcessor->setData(fProgramDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); - this->bindTextures(primProc, &nextTexSamplerIdx); + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + const GrPrimitiveProcessor::TextureSampler& sampler = primProc.textureSampler(i); + fGpu->bindTexture(nextTexSamplerIdx++, sampler.samplerState(), + static_cast(sampler.peekTexture())); + } - this->setFragmentData(primProc, pipeline, &nextTexSamplerIdx); + this->setFragmentData(pipeline, &nextTexSamplerIdx); const GrXferProcessor& xp = pipeline.getXferProcessor(); SkIPoint offset; @@ -102,31 +106,47 @@ void GrGLProgram::setData(const GrPrimitiveProcessor& primProc, const GrPipeline void GrGLProgram::generateMipmaps(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { - this->generateMipmaps(primProc); + auto genLevelsIfNeeded = [this](GrTexture* tex, const GrSamplerState& sampler) { + if (sampler.filter() == GrSamplerState::Filter::kMipMap && + tex->texturePriv().mipMapped() == GrMipMapped::kYes && + tex->texturePriv().mipMapsAreDirty()) { + SkASSERT(fGpu->caps()->mipMapSupport()); + fGpu->regenerateMipMapLevels(static_cast(tex)); + } + }; + + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + const auto& textureSampler = primProc.textureSampler(i); + genLevelsIfNeeded(textureSampler.peekTexture(), textureSampler.samplerState()); + } GrFragmentProcessor::Iter iter(pipeline); while (const GrFragmentProcessor* fp = iter.next()) { - this->generateMipmaps(*fp); + for (int i = 0; i < fp->numTextureSamplers(); ++i) { + const auto& textureSampler = fp->textureSampler(i); + genLevelsIfNeeded(textureSampler.peekTexture(), textureSampler.samplerState()); + } } } -void GrGLProgram::setFragmentData(const GrPrimitiveProcessor& primProc, - const GrPipeline& pipeline, - int* nextTexSamplerIdx) { +void GrGLProgram::setFragmentData(const GrPipeline& pipeline, int* nextTexSamplerIdx) { GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); const GrFragmentProcessor* fp = iter.next(); GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { glslFP->setData(fProgramDataManager, *fp); - this->bindTextures(*fp, nextTexSamplerIdx); + for (int i = 0; i < fp->numTextureSamplers(); ++i) { + const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i); + fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), + static_cast(sampler.peekTexture())); + } fp = iter.next(); glslFP = glslIter.next(); } SkASSERT(!fp && !glslFP); } - void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc, const GrRenderTargetProxy* proxy) { GrRenderTarget* rt = proxy->priv().peekRenderTarget(); @@ -156,25 +176,3 @@ void GrGLProgram::setRenderTargetState(const GrPrimitiveProcessor& primProc, size, proxy->origin()); } } - -void GrGLProgram::bindTextures(const GrResourceIOProcessor& processor, - int* nextTexSamplerIdx) { - for (int i = 0; i < processor.numTextureSamplers(); ++i) { - const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); - fGpu->bindTexture((*nextTexSamplerIdx)++, sampler.samplerState(), - static_cast(sampler.peekTexture())); - } -} - -void GrGLProgram::generateMipmaps(const GrResourceIOProcessor& processor) { - for (int i = 0; i < processor.numTextureSamplers(); ++i) { - const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); - auto* tex = sampler.peekTexture(); - if (sampler.samplerState().filter() == GrSamplerState::Filter::kMipMap && - tex->texturePriv().mipMapped() == GrMipMapped::kYes && - tex->texturePriv().mipMapsAreDirty()) { - SkASSERT(fGpu->caps()->mipMapSupport()); - fGpu->regenerateMipMapLevels(static_cast(sampler.peekTexture())); - } - } -} diff --git a/src/gpu/gl/GrGLProgram.h b/src/gpu/gl/GrGLProgram.h index a8a3391adc..25b6e9a84e 100644 --- a/src/gpu/gl/GrGLProgram.h +++ b/src/gpu/gl/GrGLProgram.h @@ -19,7 +19,6 @@ class GrGLSLXferProcessor; class GrPipeline; class GrPrimitiveProcessor; class GrRenderTargetProxy; -class GrResourceIOProcessor; /** * This class manages a GPU program and records per-program information. It also records the vertex @@ -140,17 +139,11 @@ public: private: // A helper to loop over effects, set the transforms (via subclass) and bind textures - void setFragmentData(const GrPrimitiveProcessor&, const GrPipeline&, int* nextTexSamplerIdx); + void setFragmentData(const GrPipeline&, int* nextTexSamplerIdx); // Helper for setData() that sets the view matrix and loads the render target height uniform void setRenderTargetState(const GrPrimitiveProcessor&, const GrRenderTargetProxy*); - // Helper for setData() that binds textures to the appropriate texture units - void bindTextures(const GrResourceIOProcessor&, int* nextSamplerIdx); - - // Helper for generateMipmaps() that ensures mipmaps are up to date - void generateMipmaps(const GrResourceIOProcessor&); - // these reflect the current values of uniforms (GL uniform values travel with program) RenderTargetState fRenderTargetState; GrGLSLBuiltinUniformHandles fBuiltinUniformHandles; diff --git a/src/gpu/glsl/GrGLSLFragmentProcessor.h b/src/gpu/glsl/GrGLSLFragmentProcessor.h index 8f903755ea..591146e925 100644 --- a/src/gpu/glsl/GrGLSLFragmentProcessor.h +++ b/src/gpu/glsl/GrGLSLFragmentProcessor.h @@ -38,7 +38,7 @@ private: * 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. */ - template + template class BuilderInputProvider { public: BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} @@ -67,10 +67,10 @@ private: }; public: - using TransformedCoordVars = BuilderInputProvider; - using TextureSamplers = BuilderInputProvider; + using TransformedCoordVars = + BuilderInputProvider; + using TextureSamplers = + BuilderInputProvider; /** 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 diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.cpp b/src/gpu/glsl/GrGLSLProgramBuilder.cpp index 05b78eef0c..b0cf8169d4 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.cpp +++ b/src/gpu/glsl/GrGLSLProgramBuilder.cpp @@ -96,8 +96,15 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr SkASSERT(!fGeometryProcessor); fGeometryProcessor.reset(proc.createGLSLInstance(*this->shaderCaps())); - SkSTArray<4, SamplerHandle> texSamplers(proc.numTextureSamplers()); - this->emitSamplers(proc, &texSamplers); + SkAutoSTMalloc<4, SamplerHandle> texSamplers(proc.numTextureSamplers()); + for (int i = 0; i < proc.numTextureSamplers(); ++i) { + SkString name; + name.printf("TextureSampler_%d", i); + const auto& sampler = proc.textureSampler(i); + GrTextureType textureType = sampler.peekTexture()->texturePriv().textureType(); + texSamplers[i] = this->emitSampler(textureType, sampler.peekTexture()->config(), + name.c_str(), sampler.visibility()); + } GrGLSLPrimitiveProcessor::FPCoordTransformHandler transformHandler(fPipeline, &fTransformedCoordVars); @@ -111,7 +118,7 @@ void GrGLSLProgramBuilder::emitAndInstallPrimProc(const GrPrimitiveProcessor& pr outputColor->c_str(), outputCoverage->c_str(), rtAdjustName, - texSamplers.begin(), + texSamplers.get(), &transformHandler); fGeometryProcessor->emitCode(args); @@ -168,15 +175,23 @@ SkString GrGLSLProgramBuilder::emitAndInstallFragProc( GrGLSLFragmentProcessor* fragProc = fp.createGLSLInstance(); - SkSTArray<4, SamplerHandle> textureSamplerArray(fp.numTextureSamplers()); - GrFragmentProcessor::Iter iter(&fp); - while (const GrFragmentProcessor* subFP = iter.next()) { - this->emitSamplers(*subFP, &textureSamplerArray); + SkSTArray<4, SamplerHandle> texSamplers; + GrFragmentProcessor::Iter fpIter(&fp); + int samplerIdx = 0; + while (const auto* subFP = fpIter.next()) { + for (int i = 0; i < subFP->numTextureSamplers(); ++i) { + SkString name; + name.printf("TextureSampler_%d", samplerIdx++); + const auto& sampler = subFP->textureSampler(i); + GrTextureType textureType = sampler.peekTexture()->texturePriv().textureType(); + texSamplers.emplace_back(this->emitSampler(textureType, sampler.peekTexture()->config(), + name.c_str(), kFragment_GrShaderFlag)); + } } const GrShaderVar* coordVars = fTransformedCoordVars.begin() + transformedCoordVarsIdx; GrGLSLFragmentProcessor::TransformedCoordVars coords(&fp, coordVars); - GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, textureSamplerArray.begin()); + GrGLSLFragmentProcessor::TextureSamplers textureSamplers(&fp, texSamplers.begin()); GrGLSLFragmentProcessor::EmitArgs args(&fFS, this->uniformHandler(), this->shaderCaps(), @@ -250,20 +265,6 @@ void GrGLSLProgramBuilder::emitAndInstallXferProc(const SkString& colorIn, fFS.codeAppend("}"); } -void GrGLSLProgramBuilder::emitSamplers( - const GrResourceIOProcessor& processor, - SkTArray* outTexSamplerHandles) { - SkString name; - int numTextureSamplers = processor.numTextureSamplers(); - for (int t = 0; t < numTextureSamplers; ++t) { - const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(t); - name.printf("TextureSampler_%d", outTexSamplerHandles->count()); - GrTextureType textureType = sampler.peekTexture()->texturePriv().textureType(); - outTexSamplerHandles->emplace_back(this->emitSampler( - textureType, sampler.peekTexture()->config(), name.c_str(), sampler.visibility())); - } -} - void GrGLSLProgramBuilder::updateSamplerCounts(GrShaderFlags visibility) { if (visibility & kVertex_GrShaderFlag) { ++fNumVertexSamplers; diff --git a/src/gpu/glsl/GrGLSLProgramBuilder.h b/src/gpu/glsl/GrGLSLProgramBuilder.h index bdc39c00dd..8d263b8e00 100644 --- a/src/gpu/glsl/GrGLSLProgramBuilder.h +++ b/src/gpu/glsl/GrGLSLProgramBuilder.h @@ -135,8 +135,6 @@ private: SkString output, SkTArray>*); void emitAndInstallXferProc(const SkString& colorIn, const SkString& coverageIn); - void emitSamplers(const GrResourceIOProcessor& processor, - SkTArray* outTexSamplerHandles); SamplerHandle emitSampler(GrTextureType, GrPixelConfig, const char* name, GrShaderFlags visibility); void emitFSOutputSwizzle(bool hasSecondaryOutput); diff --git a/src/gpu/vk/GrVkGpuCommandBuffer.cpp b/src/gpu/vk/GrVkGpuCommandBuffer.cpp index d58a8b5ff7..013c1d7815 100644 --- a/src/gpu/vk/GrVkGpuCommandBuffer.cpp +++ b/src/gpu/vk/GrVkGpuCommandBuffer.cpp @@ -608,31 +608,6 @@ GrVkPipelineState* GrVkGpuRTCommandBuffer::prepareDrawState( return pipelineState; } -static void prepare_sampled_images(const GrResourceIOProcessor& processor, - SkTArray* sampledImages, - GrVkGpu* gpu) { - for (int i = 0; i < processor.numTextureSamplers(); ++i) { - const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); - GrVkTexture* vkTexture = static_cast(sampler.peekTexture()); - - // We may need to resolve the texture first if it is also a render target - GrVkRenderTarget* texRT = static_cast(vkTexture->asRenderTarget()); - if (texRT) { - gpu->onResolveRenderTarget(texRT); - } - - // Check if we need to regenerate any mip maps - if (GrSamplerState::Filter::kMipMap == sampler.samplerState().filter() && - (vkTexture->width() != 1 || vkTexture->height() != 1)) { - SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes); - if (vkTexture->texturePriv().mipMapsAreDirty()) { - gpu->regenerateMipMapLevels(vkTexture); - } - } - sampledImages->push_back(vkTexture); - } -} - void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline, const GrPipeline::FixedDynamicState* fixedDynamicState, @@ -648,10 +623,35 @@ void GrVkGpuRTCommandBuffer::onDraw(const GrPrimitiveProcessor& primProc, CommandBufferInfo& cbInfo = fCommandBufferInfos[fCurrentCmdInfo]; - prepare_sampled_images(primProc, &cbInfo.fSampledImages, fGpu); + auto prepareSampledImage = [&](GrTexture* texture, GrSamplerState::Filter filter) { + GrVkTexture* vkTexture = static_cast(texture); + // We may need to resolve the texture first if it is also a render target + GrVkRenderTarget* texRT = static_cast(vkTexture->asRenderTarget()); + if (texRT) { + fGpu->onResolveRenderTarget(texRT); + } + + // Check if we need to regenerate any mip maps + if (GrSamplerState::Filter::kMipMap == filter && + (vkTexture->width() != 1 || vkTexture->height() != 1)) { + SkASSERT(vkTexture->texturePriv().mipMapped() == GrMipMapped::kYes); + if (vkTexture->texturePriv().mipMapsAreDirty()) { + fGpu->regenerateMipMapLevels(vkTexture); + } + } + cbInfo.fSampledImages.push_back(vkTexture); + }; + + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + const GrPrimitiveProcessor::TextureSampler& sampler = primProc.textureSampler(i); + prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter()); + } GrFragmentProcessor::Iter iter(pipeline); while (const GrFragmentProcessor* fp = iter.next()) { - prepare_sampled_images(*fp, &cbInfo.fSampledImages, fGpu); + for (int i = 0; i < fp->numTextureSamplers(); ++i) { + const GrFragmentProcessor::TextureSampler& sampler = fp->textureSampler(i); + prepareSampledImage(sampler.peekTexture(), sampler.samplerState().filter()); + } } if (GrTexture* dstTexture = pipeline.peekDstTexture()) { cbInfo.fSampledImages.push_back(static_cast(dstTexture)); diff --git a/src/gpu/vk/GrVkPipelineState.cpp b/src/gpu/vk/GrVkPipelineState.cpp index 9080128bef..8870f41e86 100644 --- a/src/gpu/vk/GrVkPipelineState.cpp +++ b/src/gpu/vk/GrVkPipelineState.cpp @@ -165,19 +165,6 @@ void GrVkPipelineState::abandonGPUResources() { } } -static void append_texture_bindings( - const GrResourceIOProcessor& processor, - SkTArray* textureBindings) { - if (int numTextureSamplers = processor.numTextureSamplers()) { - const GrResourceIOProcessor::TextureSampler** bindings = - textureBindings->push_back_n(numTextureSamplers); - int i = 0; - do { - bindings[i] = &processor.textureSampler(i); - } while (++i < numTextureSamplers); - } -} - void GrVkPipelineState::setData(GrVkGpu* gpu, const GrPrimitiveProcessor& primProc, const GrPipeline& pipeline) { @@ -187,11 +174,16 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, this->setRenderTargetState(pipeline.proxy()); - SkSTArray<8, const GrResourceIOProcessor::TextureSampler*> textureBindings; + SkAutoSTMalloc<8, SamplerBindings> samplerBindings(fNumSamplers); + int currTextureBinding = 0; fGeometryProcessor->setData(fDataManager, primProc, GrFragmentProcessor::CoordTransformIter(pipeline)); - append_texture_bindings(primProc, &textureBindings); + for (int i = 0; i < primProc.numTextureSamplers(); ++i) { + const auto& sampler = primProc.textureSampler(i); + samplerBindings[currTextureBinding++] = {sampler.samplerState(), + static_cast(sampler.peekTexture())}; + } GrFragmentProcessor::Iter iter(pipeline); GrGLSLFragmentProcessor::Iter glslIter(fFragmentProcessors.get(), fFragmentProcessorCnt); @@ -199,7 +191,11 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, GrGLSLFragmentProcessor* glslFP = glslIter.next(); while (fp && glslFP) { glslFP->setData(fDataManager, *fp); - append_texture_bindings(*fp, &textureBindings); + for (int i = 0; i < fp->numTextureSamplers(); ++i) { + const auto& sampler = fp->textureSampler(i); + samplerBindings[currTextureBinding++] = + {sampler.samplerState(), static_cast(sampler.peekTexture())}; + } fp = iter.next(); glslFP = glslIter.next(); } @@ -212,16 +208,14 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, fXferProcessor->setData(fDataManager, pipeline.getXferProcessor(), dstTexture, offset); } - GrResourceProvider* resourceProvider = gpu->getContext()->contextPriv().resourceProvider(); - - GrResourceIOProcessor::TextureSampler dstTextureSampler; if (GrTextureProxy* dstTextureProxy = pipeline.dstTextureProxy()) { - dstTextureSampler.reset(sk_ref_sp(dstTextureProxy)); - SkAssertResult(dstTextureSampler.instantiate(resourceProvider)); - textureBindings.push_back(&dstTextureSampler); + samplerBindings[currTextureBinding++] = + {GrSamplerState::ClampNearest(), + static_cast(dstTextureProxy->priv().peekTexture())}; } // Get new descriptor sets + SkASSERT(fNumSamplers == currTextureBinding); if (fNumSamplers) { if (fSamplerDescriptorSet) { fSamplerDescriptorSet->recycle(gpu); @@ -229,7 +223,7 @@ void GrVkPipelineState::setData(GrVkGpu* gpu, fSamplerDescriptorSet = gpu->resourceProvider().getSamplerDescriptorSet(fSamplerDSHandle); int samplerDSIdx = GrVkUniformHandler::kSamplerDescSet; fDescriptorSets[samplerDSIdx] = fSamplerDescriptorSet->descriptorSet(); - this->writeSamplers(gpu, textureBindings); + this->writeSamplers(gpu, samplerBindings.get()); } if (fGeometryUniformBuffer || fFragmentUniformBuffer) { @@ -307,15 +301,10 @@ void GrVkPipelineState::writeUniformBuffers(const GrVkGpu* gpu) { } } -void GrVkPipelineState::writeSamplers( - GrVkGpu* gpu, - const SkTArray& textureBindings) { - SkASSERT(fNumSamplers == textureBindings.count()); - - for (int i = 0; i < textureBindings.count(); ++i) { - GrSamplerState state = textureBindings[i]->samplerState(); - - GrVkTexture* texture = static_cast(textureBindings[i]->peekTexture()); +void GrVkPipelineState::writeSamplers(GrVkGpu* gpu, const SamplerBindings bindings[]) { + for (int i = 0; i < fNumSamplers; ++i) { + const GrSamplerState& state = bindings[i].fState; + GrVkTexture* texture = bindings[i].fTexture; fSamplers.push(gpu->resourceProvider().findOrCreateCompatibleSampler( state, texture->texturePriv().maxMipMapLevel())); diff --git a/src/gpu/vk/GrVkPipelineState.h b/src/gpu/vk/GrVkPipelineState.h index a3320e5550..1df4bb5348 100644 --- a/src/gpu/vk/GrVkPipelineState.h +++ b/src/gpu/vk/GrVkPipelineState.h @@ -25,6 +25,7 @@ class GrVkImageView; class GrVkPipeline; class GrVkPipelineLayout; class GrVkSampler; +class GrVkTexture; class GrVkUniformBuffer; /** @@ -72,9 +73,11 @@ public: private: void writeUniformBuffers(const GrVkGpu* gpu); - void writeSamplers( - GrVkGpu* gpu, - const SkTArray& textureBindings); + struct SamplerBindings { + GrSamplerState fState; + GrVkTexture* fTexture; + }; + void writeSamplers(GrVkGpu* gpu, const SamplerBindings[]); /** * We use the RT's size and origin to adjust from Skia device space to vulkan normalized device diff --git a/tests/LazyProxyTest.cpp b/tests/LazyProxyTest.cpp index 4a82d10760..3881251f6c 100644 --- a/tests/LazyProxyTest.cpp +++ b/tests/LazyProxyTest.cpp @@ -137,7 +137,7 @@ public: kBottomLeft_GrSurfaceOrigin, kAlpha_half_GrPixelConfig, *proxyProvider->caps()); fAccess.reset(fLazyProxy, GrSamplerState::Filter::kNearest, - GrSamplerState::WrapMode::kClamp, kFragment_GrShaderFlag); + GrSamplerState::WrapMode::kClamp); this->setTextureSamplerCnt(1); } -- cgit v1.2.3