Rework optimization override flags.

Previously, the Compiler optimization overrides only supported force-
disabling a particular behavior; we assumed that the default state of
a Compiler was to allow all optimizations. This assumption is about to
be invalidated, as the Inliner will soon be off by default unless you
are using GLES.

The override flags are now a tri-state; optimization and inlining can
be set to "default", "on" or "off".

Change-Id: I5637693222ca1de74ca1073c24d86c8e7c5026f6
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/390136
Commit-Queue: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 3297007..cc01495 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -72,11 +72,9 @@
 
 namespace SkSL {
 
-// Set these flags to `false` to disable optimization passes unilaterally.
 // These flags allow tools like Viewer or Nanobench to override the compiler's ProgramSettings.
-bool gSkSLOptimizer = true;
-bool gSkSLInliner = true;
-bool gSkSLDeadCodeElimination = true;
+Compiler::OverrideFlag Compiler::sOptimizer = OverrideFlag::kDefault;
+Compiler::OverrideFlag Compiler::sInliner = OverrideFlag::kDefault;
 
 using RefKind = VariableReference::RefKind;
 
@@ -405,11 +403,30 @@
     auto config = std::make_unique<ProgramConfig>(ProgramConfig{kind, settings});
     AutoProgramConfig autoConfig(fContext, config.get());
 
-    // Honor our global optimization-disable flags.
-    config->fSettings.fOptimize &= gSkSLOptimizer;
-    config->fSettings.fInlineThreshold *= (int)gSkSLInliner;
-    config->fSettings.fRemoveDeadVariables &= gSkSLDeadCodeElimination;
-    config->fSettings.fRemoveDeadFunctions &= gSkSLDeadCodeElimination;
+    // Honor our optimization-override flags.
+    switch (sOptimizer) {
+        case OverrideFlag::kDefault:
+            break;
+        case OverrideFlag::kOff:
+            config->fSettings.fOptimize = false;
+            break;
+        case OverrideFlag::kOn:
+            config->fSettings.fOptimize = true;
+            break;
+    }
+
+    switch (sInliner) {
+        case OverrideFlag::kDefault:
+            break;
+        case OverrideFlag::kOff:
+            config->fSettings.fInlineThreshold = 0;
+            break;
+        case OverrideFlag::kOn:
+            if (config->fSettings.fInlineThreshold == 0) {
+                config->fSettings.fInlineThreshold = kDefaultInlineThreshold;
+            }
+            break;
+    }
 
     // Disable optimization settings that depend on a parent setting which has been disabled.
     config->fSettings.fInlineThreshold *= (int)config->fSettings.fOptimize;
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index 007286e..de1b404 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -98,6 +98,18 @@
     Compiler& operator=(const Compiler&) = delete;
 
     /**
+     * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like
+     * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging.
+     */
+    enum class OverrideFlag {
+        kDefault,
+        kOff,
+        kOn,
+    };
+    static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; }
+    static void EnableInliner(OverrideFlag flag) { sInliner = flag; }
+
+    /**
      * If externalFunctions is supplied, those values are registered in the symbol table of the
      * Program, but ownership is *not* transferred. It is up to the caller to keep them alive.
      */
@@ -224,6 +236,9 @@
     String fErrorText;
     std::vector<size_t> fErrorTextLength;
 
+    static OverrideFlag sOptimizer;
+    static OverrideFlag sInliner;
+
     friend class AutoSource;
     friend class ::SkSLCompileBench;
     friend class dsl::DSLWriter;
diff --git a/tools/viewer/Viewer.cpp b/tools/viewer/Viewer.cpp
index 24d8488..0e6e2e5 100644
--- a/tools/viewer/Viewer.cpp
+++ b/tools/viewer/Viewer.cpp
@@ -30,6 +30,7 @@
 #include "src/gpu/ccpr/GrCoverageCountingPathRenderer.h"
 #include "src/gpu/tessellate/GrTessellationPathRenderer.h"
 #include "src/image/SkImage_Base.h"
+#include "src/sksl/SkSLCompiler.h"
 #include "src/utils/SkJSONWriter.h"
 #include "src/utils/SkOSPath.h"
 #include "tools/Resources.h"
@@ -65,11 +66,6 @@
     #include "tools/viewer/SkRiveSlide.h"
 #endif
 
-namespace SkSL {
-extern bool gSkSLOptimizer;
-extern bool gSkSLInliner;
-}
-
 class CapturingShaderErrorHandler : public GrContextOptions::ShaderErrorHandler {
 public:
     void compileError(const char* shader, const char* errors) override {
@@ -91,6 +87,8 @@
 GrContextOptions::ShaderErrorHandler* Viewer::ShaderErrorHandler() { return &gShaderErrorHandler; }
 
 using namespace sk_app;
+using SkSL::Compiler;
+using OverrideFlag = SkSL::Compiler::OverrideFlag;
 
 static std::map<GpuPathRenderers, std::string> gPathRendererNames;
 
@@ -375,7 +373,7 @@
     SetCtxOptionsFromCommonFlags(&displayParams.fGrContextOptions);
     displayParams.fGrContextOptions.fPersistentCache = &fPersistentCache;
     displayParams.fGrContextOptions.fShaderCacheStrategy =
-            GrContextOptions::ShaderCacheStrategy::kBackendSource;
+            GrContextOptions::ShaderCacheStrategy::kSkSL;
     displayParams.fGrContextOptions.fShaderErrorHandler = &gShaderErrorHandler;
     displayParams.fGrContextOptions.fSuppressPrints = true;
     displayParams.fGrContextOptions.fAlwaysAntialias = FLAGS_dmsaa;
@@ -2342,11 +2340,6 @@
                 bool sksl = params.fGrContextOptions.fShaderCacheStrategy ==
                             GrContextOptions::ShaderCacheStrategy::kSkSL;
 
-                int optLevel =                           sksl ? kShaderOptLevel_Source :
-                                           SkSL::gSkSLInliner ? kShaderOptLevel_Inline :
-                                         SkSL::gSkSLOptimizer ? kShaderOptLevel_Optimize :
-                                                                kShaderOptLevel_Compile;
-
 #if defined(SK_VULKAN)
                 const bool isVulkan = fBackendType == sk_app::Window::kVulkan_BackendType;
 #else
@@ -2401,7 +2394,7 @@
                 bool doApply     = ImGui::Button("Apply Changes"); ImGui::SameLine();
                 bool doDump      = ImGui::Button("Dump SkSL to resources/sksl/");
 
-                int newOptLevel = optLevel;
+                int newOptLevel = fOptLevel;
                 ImGui::RadioButton("SkSL", &newOptLevel, kShaderOptLevel_Source);
                 ImGui::SameLine();
                 ImGui::RadioButton("Compile", &newOptLevel, kShaderOptLevel_Compile);
@@ -2412,10 +2405,27 @@
 
                 // If we are changing the compile mode, we want to reset the cache and redo
                 // everything.
-                if (doDump || newOptLevel != optLevel) {
+                if (doDump || newOptLevel != fOptLevel) {
                     sksl = doDump || (newOptLevel == kShaderOptLevel_Source);
-                    SkSL::gSkSLOptimizer           = (newOptLevel >= kShaderOptLevel_Optimize);
-                    SkSL::gSkSLInliner             = (newOptLevel >= kShaderOptLevel_Inline);
+                    fOptLevel = (ShaderOptLevel)newOptLevel;
+                    switch (fOptLevel) {
+                        case kShaderOptLevel_Source:
+                            Compiler::EnableOptimizer(OverrideFlag::kDefault);
+                            Compiler::EnableInliner(OverrideFlag::kDefault);
+                            break;
+                        case kShaderOptLevel_Compile:
+                            Compiler::EnableOptimizer(OverrideFlag::kOff);
+                            Compiler::EnableInliner(OverrideFlag::kOff);
+                            break;
+                        case kShaderOptLevel_Optimize:
+                            Compiler::EnableOptimizer(OverrideFlag::kOn);
+                            Compiler::EnableInliner(OverrideFlag::kOff);
+                            break;
+                        case kShaderOptLevel_Inline:
+                            Compiler::EnableOptimizer(OverrideFlag::kOn);
+                            Compiler::EnableInliner(OverrideFlag::kOn);
+                            break;
+                    }
 
                     params.fGrContextOptions.fShaderCacheStrategy =
                             sksl ? GrContextOptions::ShaderCacheStrategy::kSkSL
diff --git a/tools/viewer/Viewer.h b/tools/viewer/Viewer.h
index f13a8d1..9b4700a 100644
--- a/tools/viewer/Viewer.h
+++ b/tools/viewer/Viewer.h
@@ -237,6 +237,7 @@
         kShaderOptLevel_Optimize,
         kShaderOptLevel_Inline,
     };
+    ShaderOptLevel fOptLevel = kShaderOptLevel_Source;
 };
 
 #endif