SkSL: Reduce default heap usage, improve heap benchmarks

We were always pre-loading the fragment and vertex modules, but deferred
loading all others. Those two take up about 300 KB of heap. Now, all
modules are deferred, so compiler instances that don't need them (like
the one used for runtime effects) are much smaller.

Now that we can get better fine-grained numbers, added two more
benchmarks, to track actual baseline usage, plus the usage in the two
most likely configurations.

Change-Id: Idfbcd52c8afee566ac42ab827c80c940f91c4ad7
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/337176
Commit-Queue: Brian Osman <brianosman@google.com>
Commit-Queue: John Stiles <johnstiles@google.com>
Reviewed-by: John Stiles <johnstiles@google.com>
diff --git a/bench/SkSLBench.cpp b/bench/SkSLBench.cpp
index c6fb6f0..e8121ef 100644
--- a/bench/SkSLBench.cpp
+++ b/bench/SkSLBench.cpp
@@ -570,6 +570,7 @@
         log->endObject();                // test
     };
 
+    // Heap used by a default compiler (with no modules loaded)
     {
         int before = heap_bytes_used();
         GrShaderCaps caps(GrContextOptions{});
@@ -577,6 +578,27 @@
         int after = heap_bytes_used();
         bench("sksl_compiler_baseline", after - before);
     }
+
+    // Heap used by a compiler with the two main GPU modules (fragment + vertex) loaded
+    {
+        int before = heap_bytes_used();
+        GrShaderCaps caps(GrContextOptions{});
+        SkSL::Compiler compiler(&caps);
+        compiler.moduleForProgramKind(SkSL::Program::kVertex_Kind);
+        compiler.moduleForProgramKind(SkSL::Program::kFragment_Kind);
+        int after = heap_bytes_used();
+        bench("sksl_compiler_gpu", after - before);
+    }
+
+    // Heap used by a compiler with the runtime effect module loaded
+    {
+        int before = heap_bytes_used();
+        GrShaderCaps caps(GrContextOptions{});
+        SkSL::Compiler compiler(&caps);
+        compiler.moduleForProgramKind(SkSL::Program::kPipelineStage_Kind);
+        int after = heap_bytes_used();
+        bench("sksl_compiler_runtimeeffect", after - before);
+    }
 }
 
 #else
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 801639f..fd87d9b 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -177,25 +177,45 @@
 
     fRootModule = {fRootSymbolTable, /*fIntrinsics=*/nullptr};
     fPrivateModule = {fPrivateSymbolTable, /*fIntrinsics=*/nullptr};
-
-    fGPUModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(gpu), fPrivateModule);
-    fVertexModule = this->parseModule(Program::kVertex_Kind, MODULE_DATA(vert), fGPUModule);
-    fFragmentModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(frag), fGPUModule);
 }
 
 Compiler::~Compiler() {}
 
+const ParsedModule& Compiler::loadGPUModule() {
+    if (!fGPUModule.fSymbols) {
+        fGPUModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(gpu), fPrivateModule);
+    }
+    return fGPUModule;
+}
+
+const ParsedModule& Compiler::loadFragmentModule() {
+    if (!fFragmentModule.fSymbols) {
+        fFragmentModule = this->parseModule(Program::kFragment_Kind, MODULE_DATA(frag),
+                                            this->loadGPUModule());
+    }
+    return fFragmentModule;
+}
+
+const ParsedModule& Compiler::loadVertexModule() {
+    if (!fVertexModule.fSymbols) {
+        fVertexModule = this->parseModule(Program::kVertex_Kind, MODULE_DATA(vert),
+                                          this->loadGPUModule());
+    }
+    return fVertexModule;
+}
+
 const ParsedModule& Compiler::loadGeometryModule() {
     if (!fGeometryModule.fSymbols) {
-        fGeometryModule = this->parseModule(Program::kGeometry_Kind, MODULE_DATA(geom), fGPUModule);
+        fGeometryModule = this->parseModule(Program::kGeometry_Kind, MODULE_DATA(geom),
+                                            this->loadGPUModule());
     }
     return fGeometryModule;
 }
 
 const ParsedModule& Compiler::loadFPModule() {
     if (!fFPModule.fSymbols) {
-        fFPModule =
-                this->parseModule(Program::kFragmentProcessor_Kind, MODULE_DATA(fp), fGPUModule);
+        fFPModule = this->parseModule(Program::kFragmentProcessor_Kind, MODULE_DATA(fp),
+                                      this->loadGPUModule());
     }
     return fFPModule;
 }
@@ -252,8 +272,8 @@
 
 const ParsedModule& Compiler::moduleForProgramKind(Program::Kind kind) {
     switch (kind) {
-        case Program::kVertex_Kind:            return fVertexModule;                 break;
-        case Program::kFragment_Kind:          return fFragmentModule;               break;
+        case Program::kVertex_Kind:            return this->loadVertexModule();      break;
+        case Program::kFragment_Kind:          return this->loadFragmentModule();    break;
         case Program::kGeometry_Kind:          return this->loadGeometryModule();    break;
         case Program::kFragmentProcessor_Kind: return this->loadFPModule();          break;
         case Program::kPipelineStage_Kind:     return this->loadPipelineModule();    break;
diff --git a/src/sksl/SkSLCompiler.h b/src/sksl/SkSLCompiler.h
index bf5a576..9f3be47 100644
--- a/src/sksl/SkSLCompiler.h
+++ b/src/sksl/SkSLCompiler.h
@@ -226,6 +226,9 @@
     const ParsedModule& moduleForProgramKind(Program::Kind kind);
 
 private:
+    const ParsedModule& loadGPUModule();
+    const ParsedModule& loadFragmentModule();
+    const ParsedModule& loadVertexModule();
     const ParsedModule& loadFPModule();
     const ParsedModule& loadGeometryModule();
     const ParsedModule& loadPublicModule();