Move the initial GrProgramDesc keyLength into the header

This sets up for moving GrProgramDesc creation to GrCaps. I.e., we will have a virtual "GrProgramDesc GrCaps::makeDesc(const GrRenderTarget*, const GrProgramInfo&)" call.

Bug: skia:9455
Change-Id: I82053297383af9d405e6b485bf8287f10fa15967
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/256696
Reviewed-by: Greg Daniel <egdaniel@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/gpu/GrProgramDesc.cpp b/src/gpu/GrProgramDesc.cpp
index 1821790..c2e1cca 100644
--- a/src/gpu/GrProgramDesc.cpp
+++ b/src/gpu/GrProgramDesc.cpp
@@ -239,6 +239,7 @@
     if (header->fColorFragmentProcessorCnt != programInfo.pipeline().numColorFragmentProcessors() ||
         header->fCoverageFragmentProcessorCnt !=
                                          programInfo.pipeline().numCoverageFragmentProcessors()) {
+        desc->key().reset();
         return false;
     }
     // If we knew the shader won't depend on origin, we could skip this (and use the same program
@@ -252,5 +253,13 @@
     // The base descriptor only stores whether or not the primitiveType is kPoints. Backend-
     // specific versions (e.g., Vulkan) require more detail
     header->fHasPointSize = (programInfo.primitiveType() == GrPrimitiveType::kPoints);
+
+    header->fInitialKeyLength = desc->keyLength();
+    // Fail if the initial key length won't fit in 27 bits.
+    if (header->fInitialKeyLength != desc->keyLength()) {
+        desc->key().reset();
+        return false;
+    }
+
     return true;
 }
diff --git a/src/gpu/GrProgramDesc.h b/src/gpu/GrProgramDesc.h
index 9d9ea00..775db62 100644
--- a/src/gpu/GrProgramDesc.h
+++ b/src/gpu/GrProgramDesc.h
@@ -86,6 +86,8 @@
         return !(*this == other);
     }
 
+    uint32_t initialKeyLength() const { return this->header().fInitialKeyLength; }
+
 protected:
     // TODO: this should be removed and converted to just data added to the key
     struct KeyHeader {
@@ -94,18 +96,26 @@
         uint8_t fColorFragmentProcessorCnt; // Can be packed into 4 bits if required.
         uint8_t fCoverageFragmentProcessorCnt;
         // Set to uniquely identify the rt's origin, or 0 if the shader does not require this info.
-        uint8_t fSurfaceOriginKey : 2;
-        uint8_t fProcessorFeatures : 1;
-        bool fSnapVerticesToPixelCenters : 1;
-        bool fHasPointSize : 1;
-        uint8_t fPad : 3;
+        uint32_t fSurfaceOriginKey : 2;
+        uint32_t fProcessorFeatures : 1;
+        uint32_t fSnapVerticesToPixelCenters : 1;
+        uint32_t fHasPointSize : 1;
+        // This is the key size (in bytes) after core key construction. It doesn't include any
+        // portions added by the platform-specific backends.
+        uint32_t fInitialKeyLength : 27;
     };
-    GR_STATIC_ASSERT(sizeof(KeyHeader) == 6);
+    GR_STATIC_ASSERT(sizeof(KeyHeader) == 8);
+
+    const KeyHeader& header() const { return *this->atOffset<KeyHeader, kHeaderOffset>(); }
 
     template<typename T, size_t OFFSET> T* atOffset() {
         return reinterpret_cast<T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
     }
 
+    template<typename T, size_t OFFSET> const T* atOffset() const {
+        return reinterpret_cast<const T*>(reinterpret_cast<intptr_t>(fKey.begin()) + OFFSET);
+    }
+
     // The key, stored in fKey, is composed of two parts:
     // 1. Header struct defined above.
     // 2. A Backend specific payload which includes the per-processor keys.
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.cpp b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
index 3974a68..736f004 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.cpp
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.cpp
@@ -139,7 +139,9 @@
     // Here we shear off the Vk-specific portion of the Desc in order to create the
     // persistent key. This is bc Vk only caches the SPIRV code, not the fully compiled
     // program, and that only depends on the base GrProgramDesc data.
-    sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
+    // The +4 is to include the kShader_PersistentCacheKeyType code the Vulkan backend adds
+    // to the key right after the base key.
+    sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->initialKeyLength()+4);
     sk_sp<SkData> data = GrPersistentCacheUtils::PackCachedShaders(isSkSL ? kSKSL_Tag : kSPIRV_Tag,
                                                                    shaders,
                                                                    inputs, kGrShaderTypeCount);
@@ -209,7 +211,9 @@
         // Here we shear off the Vk-specific portion of the Desc in order to create the
         // persistent key. This is bc Vk only caches the SPIRV code, not the fully compiled
         // program, and that only depends on the base GrProgramDesc data.
-        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->shaderKeyLength());
+        // The +4 is to include the kShader_PersistentCacheKeyType code the Vulkan backend adds
+        // to the key right after the base key.
+        sk_sp<SkData> key = SkData::MakeWithoutCopy(desc->asKey(), desc->initialKeyLength()+4);
         cached = persistentCache->load(*key);
         if (cached) {
             reader.setMemory(cached->data(), cached->size());
@@ -337,10 +341,12 @@
 
     GrProcessorKeyBuilder b(&desc->key());
 
+    // This will become part of the sheared off key used to persistently cache
+    // the SPIRV code. It needs to be added right after the base key so that,
+    // when the base-key is sheared off, the shearing code can include it in the
+    // reduced key (c.f. the +4s in the SkData::MakeWithCopy calls in
+    // GrVkPipelineStateBuilder.cpp).
     b.add32(GrVkGpu::kShader_PersistentCacheKeyType);
-    int keyLength = desc->key().count();
-    SkASSERT(0 == (keyLength % 4));
-    desc->fShaderKeyLength = SkToU32(keyLength);
 
     GrVkRenderTarget* vkRT = (GrVkRenderTarget*)renderTarget;
     // TODO: support failure in getSimpleRenderPass
diff --git a/src/gpu/vk/GrVkPipelineStateBuilder.h b/src/gpu/vk/GrVkPipelineStateBuilder.h
index d3c7fbd..0932654 100644
--- a/src/gpu/vk/GrVkPipelineStateBuilder.h
+++ b/src/gpu/vk/GrVkPipelineStateBuilder.h
@@ -40,11 +40,7 @@
     public:
         static bool Build(Desc*, GrRenderTarget*, const GrProgramInfo&, const GrCaps&);
 
-        size_t shaderKeyLength() const { return fShaderKeyLength; }
-
     private:
-        size_t fShaderKeyLength;
-
         typedef GrProgramDesc INHERITED;
     };