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.
Committed: https://skia.googlesource.com/skia/+/c0ea398aff8254e31152cbb94c9ab6150428e252
R=robertphillips@google.com, jvanverth@google.com
Author: bsalomon@google.com
Review URL: https://codereview.chromium.org/379113004
diff --git a/src/gpu/gl/GrGLProgramDesc.cpp b/src/gpu/gl/GrGLProgramDesc.cpp
index 2c260cd..27a1fab 100644
--- a/src/gpu/gl/GrGLProgramDesc.cpp
+++ b/src/gpu/gl/GrGLProgramDesc.cpp
@@ -14,13 +14,14 @@
#include "SkChecksum.h"
-static inline bool get_key_and_update_stats(const GrEffectStage& stage,
- const GrGLCaps& caps,
- bool useExplicitLocalCoords,
- GrEffectKeyBuilder* b,
- bool* setTrueIfReadsDst,
- bool* setTrueIfReadsPos,
- bool* setTrueIfHasVertexCode) {
+bool GrGLProgramDesc::GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrEffectKeyBuilder* b,
+ uint16_t* effectKeySize,
+ bool* setTrueIfReadsDst,
+ bool* setTrueIfReadsPos,
+ bool* setTrueIfHasVertexCode) {
const GrBackendEffectFactory& factory = stage.getEffect()->getFactory();
GrDrawEffect drawEffect(stage, useExplicitLocalCoords);
if (stage.getEffect()->willReadDstColor()) {
@@ -32,7 +33,17 @@
if (stage.getEffect()->hasVertexCode()) {
*setTrueIfHasVertexCode = true;
}
- return factory.getGLEffectKey(drawEffect, caps, b);
+ factory.getGLEffectKey(drawEffect, caps, b);
+ size_t size = b->size();
+ if (size > SK_MaxU16) {
+ *effectKeySize = 0; // suppresses a warning.
+ return false;
+ }
+ *effectKeySize = SkToU16(size);
+ if (!GrGLProgramEffects::GenEffectMetaKey(drawEffect, caps, b)) {
+ return false;
+ }
+ return true;
}
bool GrGLProgramDesc::Build(const GrDrawState& drawState,
@@ -105,43 +116,54 @@
if (!skipCoverage) {
numStages += drawState.numCoverageStages() - firstEffectiveCoverageStage;
}
- GR_STATIC_ASSERT(0 == kEffectKeyLengthsOffset % sizeof(uint32_t));
+ GR_STATIC_ASSERT(0 == kEffectKeyOffsetsAndLengthOffset % sizeof(uint32_t));
// Make room for everything up to and including the array of offsets to effect keys.
desc->fKey.reset();
- desc->fKey.push_back_n(kEffectKeyLengthsOffset + sizeof(uint32_t) * numStages);
+ desc->fKey.push_back_n(kEffectKeyOffsetsAndLengthOffset + 2 * sizeof(uint16_t) * numStages);
- size_t offset = desc->fKey.count();
- int offsetIndex = 0;
+ int offsetAndSizeIndex = 0;
bool effectKeySuccess = true;
if (!skipColor) {
for (int s = firstEffectiveColorStage; s < drawState.numColorStages(); ++s) {
- uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
- kEffectKeyLengthsOffset +
- offsetIndex * sizeof(uint32_t));
- *offsetLocation = offset;
- ++offsetIndex;
+ uint16_t* offsetAndSize =
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+ offsetAndSizeIndex * 2 * sizeof(uint16_t));
GrEffectKeyBuilder b(&desc->fKey);
- effectKeySuccess |= get_key_and_update_stats(drawState.getColorStage(s), gpu->glCaps(),
- requiresLocalCoordAttrib, &b, &readsDst,
- &readFragPosition, &hasVertexCode);
- offset += b.size();
+ uint16_t effectKeySize;
+ uint32_t effectOffset = desc->fKey.count();
+ effectKeySuccess |= GetEffectKeyAndUpdateStats(
+ drawState.getColorStage(s), gpu->glCaps(),
+ requiresLocalCoordAttrib, &b,
+ &effectKeySize, &readsDst,
+ &readFragPosition, &hasVertexCode);
+ effectKeySuccess |= (effectOffset <= SK_MaxU16);
+
+ offsetAndSize[0] = SkToU16(effectOffset);
+ offsetAndSize[1] = effectKeySize;
+ ++offsetAndSizeIndex;
}
}
if (!skipCoverage) {
for (int s = firstEffectiveCoverageStage; s < drawState.numCoverageStages(); ++s) {
- uint32_t* offsetLocation = reinterpret_cast<uint32_t*>(desc->fKey.begin() +
- kEffectKeyLengthsOffset +
- offsetIndex * sizeof(uint32_t));
- *offsetLocation = offset;
- ++offsetIndex;
+ uint16_t* offsetAndSize =
+ reinterpret_cast<uint16_t*>(desc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset +
+ offsetAndSizeIndex * 2 * sizeof(uint16_t));
+
GrEffectKeyBuilder b(&desc->fKey);
- effectKeySuccess |= get_key_and_update_stats(drawState.getCoverageStage(s),
- gpu->glCaps(), requiresLocalCoordAttrib,
- &b, &readsDst, &readFragPosition,
- &hasVertexCode);
- offset += b.size();
+ uint16_t effectKeySize;
+ uint32_t effectOffset = desc->fKey.count();
+ effectKeySuccess |= GetEffectKeyAndUpdateStats(
+ drawState.getCoverageStage(s), gpu->glCaps(),
+ requiresLocalCoordAttrib, &b,
+ &effectKeySize, &readsDst,
+ &readFragPosition, &hasVertexCode);
+ effectKeySuccess |= (effectOffset <= SK_MaxU16);
+
+ offsetAndSize[0] = SkToU16(effectOffset);
+ offsetAndSize[1] = effectKeySize;
+ ++offsetAndSizeIndex;
}
}
if (!effectKeySuccess) {
diff --git a/src/gpu/gl/GrGLProgramDesc.h b/src/gpu/gl/GrGLProgramDesc.h
index d7652f4..c8aae19 100644
--- a/src/gpu/gl/GrGLProgramDesc.h
+++ b/src/gpu/gl/GrGLProgramDesc.h
@@ -172,14 +172,20 @@
// 1. uint32_t for total key length.
// 2. uint32_t for a checksum.
// 3. Header struct defined above.
- // 4. uint32_t offsets to beginning of every effects' key (see 5).
+ // 4. An array of offsets to effect keys and their sizes (see 5). uint16_t for each
+ // offset and size.
// 5. per-effect keys. Each effect's key is a variable length array of uint32_t.
enum {
+ // Part 1.
kLengthOffset = 0,
+ // Part 2.
kChecksumOffset = kLengthOffset + sizeof(uint32_t),
+ // Part 3.
kHeaderOffset = kChecksumOffset + sizeof(uint32_t),
kHeaderSize = SkAlign4(sizeof(KeyHeader)),
- kEffectKeyLengthsOffset = kHeaderOffset + kHeaderSize,
+ // Part 4.
+ // This is the offset in the overall key to the array of per-effect offset,length pairs.
+ kEffectKeyOffsetsAndLengthOffset = kHeaderOffset + kHeaderSize,
};
template<typename T, size_t OFFSET> T* atOffset() {
@@ -194,6 +200,16 @@
KeyHeader* header() { return this->atOffset<KeyHeader, kHeaderOffset>(); }
+ // Shared code between setRandom() and Build().
+ static bool GetEffectKeyAndUpdateStats(const GrEffectStage& stage,
+ const GrGLCaps& caps,
+ bool useExplicitLocalCoords,
+ GrEffectKeyBuilder* b,
+ uint16_t* effectKeySize,
+ bool* setTrueIfReadsDst,
+ bool* setTrueIfReadsPos,
+ bool* setTrueIfHasVertexCode);
+
void finalize();
const KeyHeader& getHeader() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
@@ -212,9 +228,11 @@
}
EffectKey get(int index) const {
- const uint32_t* offsets = reinterpret_cast<const uint32_t*>(fDesc->fKey.begin() +
- kEffectKeyLengthsOffset);
- uint32_t offset = offsets[fBaseIndex + index];
+ const uint16_t* offsets = reinterpret_cast<const uint16_t*>(
+ fDesc->fKey.begin() + kEffectKeyOffsetsAndLengthOffset);
+ // We store two uint16_ts per effect, one for the offset to the effect's key and one for
+ // its length. Here we just need the offset.
+ uint16_t offset = offsets[2 * (fBaseIndex + index)];
return *reinterpret_cast<const EffectKey*>(fDesc->fKey.begin() + offset);
}
private:
@@ -225,7 +243,7 @@
enum {
kMaxPreallocEffects = 8,
kIntsPerEffect = 4, // This is an overestimate of the average effect key size.
- kPreAllocSize = kEffectKeyLengthsOffset +
+ kPreAllocSize = kEffectKeyOffsetsAndLengthOffset +
kMaxPreallocEffects * sizeof(uint32_t) * kIntsPerEffect,
};
diff --git a/src/gpu/gl/GrGLProgramEffects.cpp b/src/gpu/gl/GrGLProgramEffects.cpp
index 65d14fd..9936aa5 100644
--- a/src/gpu/gl/GrGLProgramEffects.cpp
+++ b/src/gpu/gl/GrGLProgramEffects.cpp
@@ -114,6 +114,27 @@
////////////////////////////////////////////////////////////////////////////////
+bool GrGLProgramEffects::GenEffectMetaKey(const GrDrawEffect& drawEffect, const GrGLCaps& caps,
+ GrEffectKeyBuilder* b) {
+
+ EffectKey textureKey = GrGLProgramEffects::GenTextureKey(drawEffect, caps);
+ EffectKey transformKey = GrGLProgramEffects::GenTransformKey(drawEffect);
+ EffectKey attribKey = GrGLProgramEffects::GenAttribKey(drawEffect);
+ uint32_t classID = drawEffect.effect()->getFactory().effectClassID();
+
+ // Currently we allow 16 bits for each of the above portions of the meta-key. Fail if they
+ // don't fit.
+ static const uint32_t kMetaKeyInvalidMask = ~((uint32_t) SK_MaxU16);
+ if ((textureKey | transformKey | attribKey | classID) & kMetaKeyInvalidMask) {
+ return false;
+ }
+
+ uint32_t* key = b->add32n(2);
+ key[0] = (textureKey << 16 | transformKey);
+ key[1] = (classID << 16 | attribKey);
+ return true;
+}
+
EffectKey GrGLProgramEffects::GenAttribKey(const GrDrawEffect& drawEffect) {
EffectKey key = 0;
int numAttributes = drawEffect.getVertexAttribIndexCount();
diff --git a/src/gpu/gl/GrGLProgramEffects.h b/src/gpu/gl/GrGLProgramEffects.h
index 5a2fefd..c4d8843 100644
--- a/src/gpu/gl/GrGLProgramEffects.h
+++ b/src/gpu/gl/GrGLProgramEffects.h
@@ -9,9 +9,9 @@
#define GrGLProgramEffects_DEFINED
#include "GrBackendEffectFactory.h"
+#include "GrGLUniformManager.h"
#include "GrTexture.h"
#include "GrTextureAccess.h"
-#include "GrGLUniformManager.h"
class GrEffect;
class GrEffectStage;
@@ -31,11 +31,14 @@
typedef GrGLUniformManager::UniformHandle UniformHandle;
/**
- * These methods generate different portions of an effect's final key.
+ * This class emits some of the code inserted into the shaders for an effect. The code it
+ * creates may be dependent on properties of the effect that the effect itself doesn't use
+ * in its key (e.g. the pixel format of textures used). So this class inserts a meta-key for
+ * every effect using this function. It is also responsible for inserting the effect's class ID
+ * which must be different for every GrEffect subclass. It can fail if an effect uses too many
+ * textures, attributes, etc for the space allotted in the meta-key.
*/
- static EffectKey GenAttribKey(const GrDrawEffect&);
- static EffectKey GenTransformKey(const GrDrawEffect&);
- static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
+ static bool GenEffectMetaKey(const GrDrawEffect&, const GrGLCaps&, GrEffectKeyBuilder*);
virtual ~GrGLProgramEffects();
@@ -98,6 +101,13 @@
typedef SkTArray<TextureSampler> TextureSamplerArray;
protected:
+ /**
+ * Helpers for GenEffectMetaKey.
+ */
+ static EffectKey GenAttribKey(const GrDrawEffect&);
+ static EffectKey GenTransformKey(const GrDrawEffect&);
+ static EffectKey GenTextureKey(const GrDrawEffect&, const GrGLCaps&);
+
GrGLProgramEffects(int reserveCount)
: fGLEffects(reserveCount)
, fSamplers(reserveCount) {