diff options
-rw-r--r-- | include/private/GrSurfaceProxyRef.h | 28 | ||||
-rw-r--r-- | src/effects/imagefilters/SkDisplacementMapEffect.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrFragmentProcessor.cpp | 63 | ||||
-rw-r--r-- | src/gpu/GrFragmentProcessor.h | 120 | ||||
-rw-r--r-- | src/gpu/GrPipeline.cpp | 2 | ||||
-rw-r--r-- | src/gpu/GrPrimitiveProcessor.cpp | 68 | ||||
-rw-r--r-- | src/gpu/GrPrimitiveProcessor.h | 101 | ||||
-rw-r--r-- | src/gpu/GrProcessor.cpp | 77 | ||||
-rw-r--r-- | src/gpu/GrProcessor.h | 122 | ||||
-rw-r--r-- | src/gpu/GrProcessorSet.h | 2 | ||||
-rw-r--r-- | src/gpu/GrProgramDesc.cpp | 59 | ||||
-rw-r--r-- | src/gpu/ccpr/GrCCClipProcessor.cpp | 2 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.cpp | 60 | ||||
-rw-r--r-- | src/gpu/gl/GrGLProgram.h | 9 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLFragmentProcessor.h | 10 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLProgramBuilder.cpp | 45 | ||||
-rw-r--r-- | src/gpu/glsl/GrGLSLProgramBuilder.h | 2 | ||||
-rw-r--r-- | src/gpu/vk/GrVkGpuCommandBuffer.cpp | 54 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipelineState.cpp | 53 | ||||
-rw-r--r-- | src/gpu/vk/GrVkPipelineState.h | 9 | ||||
-rw-r--r-- | 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<GrSurfaceProxy>, 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<GrSurfaceProxy>, 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<GrSurfaceProxy>, GrIOType); - - /** ioType expresses what type of IO operations will be marked as - pending on the resource when markPendingIO is called. */ - void setProxy(sk_sp<GrSurfaceProxy>, 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<void(GrSurfaceProxy*)>& 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<GrTextureProxy> proxy, + const GrSamplerState& samplerState) { + this->reset(std::move(proxy), samplerState); +} + +GrFragmentProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY) { + this->reset(std::move(proxy), filterMode, wrapXAndY); +} + +void GrFragmentProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> 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<GrTextureProxy> 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 <typename T, typename BASE, - int (BASE::*COUNT)() const, - const T& (BASE::*GET)(int) const> + template <typename T, int (GrFragmentProcessor::*COUNT)() const, + const T& (GrFragmentProcessor::*GET)(int)const> class FPItemIter : public SkNoncopyable { public: explicit FPItemIter(const GrFragmentProcessor* fp) @@ -243,21 +247,14 @@ public: }; using CoordTransformIter = FPItemIter<GrCoordTransform, - GrFragmentProcessor, &GrFragmentProcessor::numCoordTransforms, &GrFragmentProcessor::coordTransform>; using TextureAccessIter = FPItemIter<TextureSampler, - GrResourceIOProcessor, - &GrResourceIOProcessor::numTextureSamplers, - &GrResourceIOProcessor::textureSampler>; - - void visitProxies(const std::function<void(GrSurfaceProxy*)>& func) { - GrFragmentProcessor::TextureAccessIter iter(this); - while (const GrResourceIOProcessor::TextureSampler* sampler = iter.next()) { - func(sampler->proxy()); - } - } + &GrFragmentProcessor::numTextureSamplers, + &GrFragmentProcessor::textureSampler>; + + void visitProxies(const std::function<void(GrSurfaceProxy*)>& func); protected: enum OptimizationFlags : uint32_t { @@ -337,6 +334,22 @@ protected: */ int registerChildProcessor(std::unique_ptr<GrFragmentProcessor> child); + void setTextureSamplerCnt(int cnt) { + SkASSERT(cnt >= 0); + fTextureSamplerCnt = cnt; + } + + /** + * Helper for implementing onTextureSampler(). E.g.: + * return IthTexureSampler(i, fMyFirstSampler, fMySecondSampler, fMyThirdSampler); + */ + template <typename... Args> + 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<GrFragmentProcessor>, 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<GrTextureProxy>, const GrSamplerState&); + + explicit TextureSampler(sk_sp<GrTextureProxy>, + GrSamplerState::Filter = GrSamplerState::Filter::kNearest, + GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp); + + TextureSampler& operator=(const TextureSampler&) = delete; + + void reset(sk_sp<GrTextureProxy>, const GrSamplerState&); + void reset(sk_sp<GrTextureProxy>, + 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<const GrCoordTransform*, true>& coords, int numCoords) const { @@ -87,3 +119,37 @@ GrPrimitiveProcessor::getTransformKey(const SkTArray<const GrCoordTransform*, tr } return totalKey; } + +/////////////////////////////////////////////////////////////////////////////////////////////////// + +GrPrimitiveProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy, + const GrSamplerState& samplerState, + GrShaderFlags visibility) { + this->reset(std::move(proxy), samplerState, visibility); +} + +GrPrimitiveProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy, + GrSamplerState::Filter filterMode, + GrSamplerState::WrapMode wrapXAndY, + GrShaderFlags visibility) { + this->reset(std::move(proxy), filterMode, wrapXAndY, visibility); +} + +void GrPrimitiveProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> 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<GrTextureProxy> 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,27 +135,112 @@ 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 <typename... Args> + 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<GrTextureProxy>, const GrSamplerState&, GrShaderFlags visibility); + + explicit TextureSampler(sk_sp<GrTextureProxy>, + 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<GrTextureProxy>, const GrSamplerState&, + GrShaderFlags visibility = kFragment_GrShaderFlag); + void reset(sk_sp<GrTextureProxy>, + 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 * with C++11. 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<GrTextureProxy> proxy, - const GrSamplerState& samplerState) { - this->reset(std::move(proxy), samplerState); -} - -GrResourceIOProcessor::TextureSampler::TextureSampler(sk_sp<GrTextureProxy> proxy, - GrSamplerState::Filter filterMode, - GrSamplerState::WrapMode wrapXAndY, - GrShaderFlags visibility) { - this->reset(std::move(proxy), filterMode, wrapXAndY, visibility); -} - -void GrResourceIOProcessor::TextureSampler::reset(sk_sp<GrTextureProxy> 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<GrTextureProxy> 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 <typename... Args> - 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<GrTextureProxy>, const GrSamplerState&); - - explicit TextureSampler(sk_sp<GrTextureProxy>, - GrSamplerState::Filter = GrSamplerState::Filter::kNearest, - GrSamplerState::WrapMode wrapXAndY = GrSamplerState::WrapMode::kClamp, - GrShaderFlags visibility = kFragment_GrShaderFlag); - - TextureSampler& operator=(const TextureSampler&) = delete; - - void reset(sk_sp<GrTextureProxy>, const GrSamplerState&, - GrShaderFlags visibility = kFragment_GrShaderFlag); - void reset(sk_sp<GrTextureProxy>, - 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<void(GrSurfaceProxy*)>& 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<uint16_t*>(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<uint16_t*>(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<GrGLTexture*>(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<GrGLTexture*>(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<GrGLTexture*>(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<GrGLTexture*>(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<GrGLTexture*>(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 <typename T, typename FPBASE, int (FPBASE::*COUNT)() const> + template <typename T, int (GrFragmentProcessor::*COUNT)() const> class BuilderInputProvider { public: BuilderInputProvider(const GrFragmentProcessor* fp, const T* ts) : fFP(fp) , fTs(ts) {} @@ -67,10 +67,10 @@ private: }; public: - using TransformedCoordVars = BuilderInputProvider<GrShaderVar, GrFragmentProcessor, - &GrFragmentProcessor::numCoordTransforms>; - using TextureSamplers = BuilderInputProvider<SamplerHandle, GrResourceIOProcessor, - &GrResourceIOProcessor::numTextureSamplers>; + using TransformedCoordVars = + BuilderInputProvider<GrShaderVar, &GrFragmentProcessor::numCoordTransforms>; + using TextureSamplers = + BuilderInputProvider<SamplerHandle, &GrFragmentProcessor::numTextureSamplers>; /** 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<SamplerHandle>* 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<std::unique_ptr<GrGLSLFragmentProcessor>>*); void emitAndInstallXferProc(const SkString& colorIn, const SkString& coverageIn); - void emitSamplers(const GrResourceIOProcessor& processor, - SkTArray<SamplerHandle>* 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<GrVkImage*>* sampledImages, - GrVkGpu* gpu) { - for (int i = 0; i < processor.numTextureSamplers(); ++i) { - const GrResourceIOProcessor::TextureSampler& sampler = processor.textureSampler(i); - GrVkTexture* vkTexture = static_cast<GrVkTexture*>(sampler.peekTexture()); - - // We may need to resolve the texture first if it is also a render target - GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(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<GrVkTexture*>(texture); + // We may need to resolve the texture first if it is also a render target + GrVkRenderTarget* texRT = static_cast<GrVkRenderTarget*>(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<GrVkTexture*>(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<const GrResourceIOProcessor::TextureSampler*>* 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<GrVkTexture*>(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<GrVkTexture*>(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<GrVkTexture*>(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<const GrResourceIOProcessor::TextureSampler*>& textureBindings) { - SkASSERT(fNumSamplers == textureBindings.count()); - - for (int i = 0; i < textureBindings.count(); ++i) { - GrSamplerState state = textureBindings[i]->samplerState(); - - GrVkTexture* texture = static_cast<GrVkTexture*>(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<const GrResourceIOProcessor::TextureSampler*>& 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); } |