From c0ea398aff8254e31152cbb94c9ab6150428e252 Mon Sep 17 00:00:00 2001 From: bsalomon Date: Tue, 15 Jul 2014 19:41:17 -0700 Subject: Makes GrGLProgramDesc's key store the lengths as well as offsets of the effect keys. Makes it possible to use GrBackendEffectFactories other than GrTBEF by moving meta-key generation out of GrTBEF. Cleans up docs around GrBackendEffectFactory. R=robertphillips@google.com, jvanverth@google.com Author: bsalomon@google.com Review URL: https://codereview.chromium.org/379113004 --- include/gpu/GrBackendEffectFactory.h | 87 +++++++++++++++++++++++------------ include/gpu/GrTBackendEffectFactory.h | 56 +++++++++++----------- 2 files changed, 85 insertions(+), 58 deletions(-) (limited to 'include') diff --git a/include/gpu/GrBackendEffectFactory.h b/include/gpu/GrBackendEffectFactory.h index 32f14f2746..ef9e436401 100644 --- a/include/gpu/GrBackendEffectFactory.h +++ b/include/gpu/GrBackendEffectFactory.h @@ -14,22 +14,12 @@ #include "SkTypes.h" #include "SkTArray.h" -/** Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific - effect object. Also tracks equivalence of shaders generated via a key. Each factory instance - is assigned a generation ID at construction. The ID of the return of GrEffect::getFactory() - is used as a type identifier. Thus a GrEffect subclass must return a singleton from - getFactory(). GrEffect subclasses should use the derived class GrTBackendEffectFactory that is - templated on the GrEffect subclass as their factory object. It requires that the GrEffect - subclass has a nested class (or typedef) GLEffect which is its GL implementation and a subclass - of GrGLEffect. - */ - class GrGLEffect; class GrGLCaps; class GrDrawEffect; /** - * Used by effects to build their keys. It incorpates each per-effect key into a larger shader key. + * Used by effects to build their keys. It incorporates each per-effect key into a larger shader key. */ class GrEffectKeyBuilder { public: @@ -42,6 +32,14 @@ public: fData->push_back_n(4, reinterpret_cast(&v)); } + /** Inserts count uint32_ts into the key. The returned pointer is only valid until the next + add*() call. */ + uint32_t* SK_WARN_UNUSED_RESULT add32n(int count) { + SkASSERT(count > 0); + fCount += count; + return reinterpret_cast(fData->push_back_n(4 * count)); + } + size_t size() const { return sizeof(uint32_t) * fCount; } private: @@ -49,43 +47,74 @@ private: int fCount; // number of uint32_ts added to fData by the effect. }; +/** + * Given a GrEffect of a particular type, creates the corresponding graphics-backend-specific + * effect object. It also tracks equivalence of shaders generated via a key. The factory for an + * effect is accessed via GrEffect::getFactory(). Each factory instance is assigned an ID at + * construction. The ID of GrEffect::getFactory() is used as a type identifier. Thus, a GrEffect + * subclass must always return the same object from getFactory() and that factory object must be + * unique to the GrEffect subclass (and unique from any further derived subclasses). + * + * Rather than subclassing this class themselves, it is recommended that GrEffect authors use + * the templated subclass GrTBackendEffectFactory by writing their getFactory() method as: + * + * const GrBackendEffectFactory& MyEffect::getFactory() const { + * return GrTBackendEffectFactory::getInstance(); + * } + * + * Using GrTBackendEffectFactory places a few constraints on the effect. See that class's comments. + */ class GrBackendEffectFactory : SkNoncopyable { public: typedef uint32_t EffectKey; - virtual bool getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0; + /** + * Generates an effect's key. The key is based on the aspects of the GrEffect object's + * configuration that affect GLSL code generation. Two GrEffect instances that would cause + * this->createGLInstance()->emitCode() to produce different code must produce different keys. + */ + virtual void getGLEffectKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*) const = 0; + + /** + * Creates a GrGLEffect instance that is used both to generate code for the GrEffect in a GLSL + * program and to manage updating uniforms for the program when it is used. + */ virtual GrGLEffect* createGLInstance(const GrDrawEffect&) const = 0; - bool operator ==(const GrBackendEffectFactory& b) const { - return fEffectClassID == b.fEffectClassID; - } - bool operator !=(const GrBackendEffectFactory& b) const { - return !(*this == b); - } - + /** + * Produces a human-reable name for the effect. + */ virtual const char* name() const = 0; + /** + * A unique value for every instance of this factory. It is automatically incorporated into the + * effect's key. This allows keys generated by getGLEffectKey() to only be unique within a + * GrEffect subclass and not necessarily across subclasses. + */ + uint32_t effectClassID() const { return fEffectClassID; } + protected: + GrBackendEffectFactory() : fEffectClassID(GenID()) {} + virtual ~GrBackendEffectFactory() {} + +private: enum { kIllegalEffectClassID = 0, }; - GrBackendEffectFactory() { - fEffectClassID = kIllegalEffectClassID; - } - virtual ~GrBackendEffectFactory() {} - - static int32_t GenID() { + static uint32_t GenID() { // fCurrEffectClassID has been initialized to kIllegalEffectClassID. The // atomic inc returns the old value not the incremented value. So we add // 1 to the returned value. - int32_t id = sk_atomic_inc(&fCurrEffectClassID) + 1; + uint32_t id = static_cast(sk_atomic_inc(&fCurrEffectClassID)) + 1; + if (!id) { + SkFAIL("This should never wrap as it should only be called once for each GrEffect " + "subclass."); + } return id; } - int32_t fEffectClassID; - -private: + const uint32_t fEffectClassID; static int32_t fCurrEffectClassID; }; diff --git a/include/gpu/GrTBackendEffectFactory.h b/include/gpu/GrTBackendEffectFactory.h index cd4c0a49e9..251e8c7768 100644 --- a/include/gpu/GrTBackendEffectFactory.h +++ b/include/gpu/GrTBackendEffectFactory.h @@ -13,7 +13,26 @@ #include "gl/GrGLProgramEffects.h" /** - * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton. + * Implements GrBackendEffectFactory for a GrEffect subclass as a singleton. This can be used by + * most GrEffect subclasses to implement the GrEffect::getFactory() method: + * + * const GrBackendEffectFactory& MyEffect::getFactory() const { + * return GrTBackendEffectFactory::getInstance(); + * } + * + * Using this class requires that the GrEffect subclass always produces the same GrGLEffect + * subclass. Additionally, It adds the following requirements to the GrEffect and GrGLEffect + * subclasses: + * + * 1. The GrGLEffect used by GrEffect subclass MyEffect must be named or typedef'ed to + * MyEffect::GLEffect. + * 2. MyEffect::GLEffect must have a static function: + * EffectKey GenKey(const GrDrawEffect, const GrGLCaps&) + * which generates a key that maps 1 to 1 with code variations emitted by + * MyEffect::GLEffect::emitCode(). + * 3. MyEffect must have a static function: + * const char* Name() + * which returns a human-readable name for the effect. */ template class GrTBackendEffectFactory : public GrBackendEffectFactory { @@ -21,35 +40,17 @@ class GrTBackendEffectFactory : public GrBackendEffectFactory { public: typedef typename EffectClass::GLEffect GLEffect; - /** Returns a human-readable name that is accessible via GrEffect or - GrGLEffect and is consistent between the two of them. - */ + /** Returns a human-readable name for the effect. Implemented using GLEffect::Name as described + * in this class's comment. */ virtual const char* name() const SK_OVERRIDE { return EffectClass::Name(); } - /** Generates an effect's key. This enables caching of generated shaders. Part of the - id identifies the GrEffect subclass. The remainder is based on the aspects of the - GrEffect object's configuration that affect GLSL code generation. If this fails - then program generation should be aborted. Failure occurs if the effect uses more - transforms, attributes, or textures than the key has space for. */ - virtual bool getGLEffectKey(const GrDrawEffect& drawEffect, + + /** Implemented using GLEffect::GenKey as described in this class's comment. */ + virtual void getGLEffectKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps, GrEffectKeyBuilder* b) const SK_OVERRIDE { - SkASSERT(kIllegalEffectClassID != fEffectClassID); EffectKey effectKey = GLEffect::GenKey(drawEffect, caps); - EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps); - EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect); - EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect); - static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16); - if ((textureKey | transformKey | attribKey | fEffectClassID) & kMetaKeyInvalidMask) { - return false; - } - - // effectKey must be first because it is what will be returned by - // GrGLProgramDesc::EffectKeyProvider and passed to the GrGLEffect as its key. b->add32(effectKey); - b->add32(textureKey << 16 | transformKey); - b->add32(fEffectClassID << 16 | attribKey); - return true; } /** Returns a new instance of the appropriate *GL* implementation class @@ -59,8 +60,7 @@ public: return SkNEW_ARGS(GLEffect, (*this, drawEffect)); } - /** This class is a singleton. This function returns the single instance. - */ + /** This class is a singleton. This function returns the single instance. */ static const GrBackendEffectFactory& getInstance() { static SkAlignedSTStorage<1, GrTBackendEffectFactory> gInstanceMem; static const GrTBackendEffectFactory* gInstance; @@ -72,9 +72,7 @@ public: } protected: - GrTBackendEffectFactory() { - fEffectClassID = GenID(); - } + GrTBackendEffectFactory() {} }; #endif -- cgit v1.2.3