Move SkSL caching out of GR_TEST_UTILS, trim persistent cache options

Combines the two boolean options into a single tri-state enum. Old GLSL
option is still present (temporarily) until Chrome is switched over.

Also add a type tag for cached program binaries, so we can safely
detect cache entries of the wrong type.

Change-Id: I0ddeefa9180b27bc2c46e2e7b77e6c9cdf4a730a
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/238856
Commit-Queue: Brian Osman <brianosman@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
diff --git a/src/gpu/gl/builders/GrGLProgramBuilder.cpp b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
index 25e718f..b08eda3 100644
--- a/src/gpu/gl/builders/GrGLProgramBuilder.cpp
+++ b/src/gpu/gl/builders/GrGLProgramBuilder.cpp
@@ -146,6 +146,7 @@
 
 static constexpr SkFourByteTag kSKSL_Tag = SkSetFourByteTag('S', 'K', 'S', 'L');
 static constexpr SkFourByteTag kGLSL_Tag = SkSetFourByteTag('G', 'L', 'S', 'L');
+static constexpr SkFourByteTag kGLPB_Tag = SkSetFourByteTag('G', 'L', 'P', 'B');
 
 void GrGLProgramBuilder::storeShaderInCache(const SkSL::Program::Inputs& inputs, GrGLuint programID,
                                             const SkSL::String shaders[], bool isSkSL) {
@@ -159,6 +160,8 @@
         GL_CALL(GetProgramiv(programID, GL_PROGRAM_BINARY_LENGTH, &length));
         if (length > 0) {
             SkWriter32 writer;
+            writer.write32(kGLPB_Tag);
+
             writer.writePad(&inputs, sizeof(inputs));
             writer.write32(length);
 
@@ -221,58 +224,58 @@
         &fGS.fCompilerString,
         &fFS.fCompilerString,
     };
-#if GR_TEST_UTILS
     SkSL::String cached_sksl[kGrShaderTypeCount];
-#endif
     if (cached) {
-        if (fGpu->glCaps().programBinarySupport()) {
-            // binary cache hit, just hand the binary to GL
-            SkReader32 reader(fCached->data(), fCached->size());
-            reader.read(&inputs, sizeof(inputs));
-            GrGLsizei length = reader.readInt();
-            const void* binary = reader.skip(length);
-            GrGLenum binaryFormat = reader.readU32();
-            GrGLClearErr(this->gpu()->glInterface());
-            GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
-                                  ProgramBinary(programID, binaryFormat, const_cast<void*>(binary),
-                                                length));
-            if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
-                if (checkLinked) {
-                    cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
+        SkReader32 reader(fCached->data(), fCached->size());
+        SkFourByteTag shaderType = reader.readU32();
+
+        switch (shaderType) {
+            case kGLPB_Tag: {
+                // Program binary cache hit. We may opt not to use this if we don't trust program
+                // binaries on this driver
+                if (!fGpu->glCaps().programBinarySupport()) {
+                    cached = false;
+                    break;
                 }
-                if (cached) {
-                    this->addInputVars(inputs);
-                    this->computeCountsAndStrides(programID, primProc, false);
+                reader.read(&inputs, sizeof(inputs));
+                GrGLsizei length = reader.readInt();
+                const void* binary = reader.skip(length);
+                GrGLenum binaryFormat = reader.readU32();
+                GrGLClearErr(this->gpu()->glInterface());
+                GR_GL_CALL_NOERRCHECK(this->gpu()->glInterface(),
+                                      ProgramBinary(programID, binaryFormat,
+                                                    const_cast<void*>(binary), length));
+                if (GR_GL_GET_ERROR(this->gpu()->glInterface()) == GR_GL_NO_ERROR) {
+                    if (checkLinked) {
+                        cached = this->checkLinkStatus(programID, errorHandler, nullptr, nullptr);
+                    }
+                    if (cached) {
+                        this->addInputVars(inputs);
+                        this->computeCountsAndStrides(programID, primProc, false);
+                    }
+                } else {
+                    cached = false;
                 }
-            } else {
-                cached = false;
+                usedProgramBinaries = cached;
+                break;
             }
-            usedProgramBinaries = cached;
-#if GR_TEST_UTILS
-        } else if (fGpu->getContext()->priv().options().fCacheSKSL) {
-            // Only switch to the stored SkSL if it unpacks correctly
-            if (kSKSL_Tag == GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
-                                                                         cached_sksl,
-                                                                         &inputs, 1)) {
+
+            case kGLSL_Tag:
+                // Source cache hit, we don't need to compile the SkSL->GLSL
+                GrPersistentCacheUtils::UnpackCachedShaders(&reader, glsl, &inputs, 1);
+                break;
+
+            case kSKSL_Tag:
+                // SkSL cache hit, this should only happen in tools overriding the generated SkSL
+                GrPersistentCacheUtils::UnpackCachedShaders(&reader, cached_sksl, &inputs, 1);
                 for (int i = 0; i < kGrShaderTypeCount; ++i) {
                     sksl[i] = &cached_sksl[i];
                 }
-            }
-#endif
-        } else {
-            // source cache hit, we don't need to compile the SkSL->GLSL
-            // It's unlikely, but if we get the wrong kind of shader back, don't use the strings
-            if (kGLSL_Tag != GrPersistentCacheUtils::UnpackCachedShaders(fCached.get(),
-                                                                         glsl,
-                                                                         &inputs, 1)) {
-                for (int i = 0; i < kGrShaderTypeCount; ++i) {
-                    glsl[i].clear();
-                }
-            }
+                break;
         }
     }
-    if (!cached || !fGpu->glCaps().programBinarySupport()) {
-        // either a cache miss, or we can't store binaries in the cache
+    if (!usedProgramBinaries) {
+        // either a cache miss, or we got something other than binaries from the cache
         if (glsl[kFragment_GrShaderType].empty()) {
             // Don't have cached GLSL, need to compile SkSL->GLSL
             if (fFS.fForceHighPrecision) {
@@ -368,14 +371,13 @@
     // black-list caching these programs in all cases. See: anglebug.com/3619
     if (!cached && !primProc.isPathRendering()) {
         bool isSkSL = false;
-#if GR_TEST_UTILS
-        if (fGpu->getContext()->priv().options().fCacheSKSL) {
+        if (fGpu->getContext()->priv().options().fShaderCacheStrategy ==
+                GrContextOptions::ShaderCacheStrategy::kSkSL) {
             for (int i = 0; i < kGrShaderTypeCount; ++i) {
                 glsl[i] = GrShaderUtils::PrettyPrint(*sksl[i]);
             }
             isSkSL = true;
         }
-#endif
         this->storeShaderInCache(inputs, programID, glsl, isSkSL);
     }
     return this->createProgram(programID);