sksl programs can now directly query GLSL caps

This adds support for querying "sk_Caps.<cap>" directly from within an SkSL program.
Combined with the existing support for collapsing 'if' statements with constant tests,
this means we can query caps using ordinary 'if' statements and the tests will 
collapse out at compile time.

BUG=skia:

GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=4795

Change-Id: I24d716a7fe6abf1489760bf08189164264269076
Reviewed-on: https://skia-review.googlesource.com/4795
Commit-Queue: Ethan Nicholas <ethannicholas@google.com>
Reviewed-by: Ben Wagner <benjaminwagner@google.com>
diff --git a/src/sksl/SkSLCompiler.cpp b/src/sksl/SkSLCompiler.cpp
index 905eff4..62e5fa7 100644
--- a/src/sksl/SkSLCompiler.cpp
+++ b/src/sksl/SkSLCompiler.cpp
@@ -135,6 +135,11 @@
     ADD_TYPE(GSampler2DArrayShadow);
     ADD_TYPE(GSamplerCubeArrayShadow);
 
+    SkString skCapsName("sk_Caps");
+    Variable* skCaps = new Variable(Position(), Modifiers(), skCapsName, 
+                                    *fContext.fSkCaps_Type, Variable::kGlobal_Storage);
+    fIRGenerator->fSymbolTable->add(skCapsName, std::unique_ptr<Symbol>(skCaps));
+
     Modifiers::Flag ignored1;
     std::vector<std::unique_ptr<ProgramElement>> ignored2;
     this->internalConvertProgram(SkString(SKSL_INCLUDE), &ignored1, &ignored2);
@@ -383,10 +388,11 @@
     }
 }
 
-std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text) {
+std::unique_ptr<Program> Compiler::convertProgram(Program::Kind kind, SkString text,
+                                                  std::unordered_map<SkString, CapValue> caps) {
     fErrorText = "";
     fErrorCount = 0;
-    fIRGenerator->pushSymbolTable();
+    fIRGenerator->start(&caps);
     std::vector<std::unique_ptr<ProgramElement>> elements;
     Modifiers::Flag ignored;
     switch (kind) {
@@ -402,7 +408,7 @@
     this->internalConvertProgram(text, &defaultPrecision, &elements);
     auto result = std::unique_ptr<Program>(new Program(kind, defaultPrecision, std::move(elements),
                                                        fIRGenerator->fSymbolTable));
-    fIRGenerator->popSymbolTable();
+    fIRGenerator->finish();
     this->writeErrorCount();
     return result;
 }
@@ -428,7 +434,8 @@
 }
 
 bool Compiler::toSPIRV(Program::Kind kind, const SkString& text, SkWStream& out) {
-    auto program = this->convertProgram(kind, text);
+    std::unordered_map<SkString, CapValue> capsMap;
+    auto program = this->convertProgram(kind, text, capsMap);
     if (fErrorCount == 0) {
         SkSL::SPIRVCodeGenerator cg(&fContext);
         cg.generateCode(*program.get(), out);
@@ -446,9 +453,32 @@
     return result;
 }
 
+static void fill_caps(const GrGLSLCaps& caps, std::unordered_map<SkString, CapValue>* capsMap) {
+#define CAP(name) capsMap->insert(std::make_pair(SkString(#name), CapValue(caps.name())));
+    CAP(fbFetchSupport);
+    CAP(fbFetchNeedsCustomOutput);
+    CAP(bindlessTextureSupport);
+    CAP(dropsTileOnZeroDivide);
+    CAP(flatInterpolationSupport);
+    CAP(noperspectiveInterpolationSupport);
+    CAP(multisampleInterpolationSupport);
+    CAP(sampleVariablesSupport);
+    CAP(sampleMaskOverrideCoverageSupport);
+    CAP(externalTextureSupport);
+    CAP(texelFetchSupport);
+    CAP(imageLoadStoreSupport);
+    CAP(mustEnableAdvBlendEqs);
+    CAP(mustEnableSpecificAdvBlendEqs);
+    CAP(mustDeclareFragmentShaderOutput);
+    CAP(canUseAnyFunctionInShader);
+#undef CAP
+}
+
 bool Compiler::toGLSL(Program::Kind kind, const SkString& text, const GrGLSLCaps& caps,
                       SkWStream& out) {
-    auto program = this->convertProgram(kind, text);
+    std::unordered_map<SkString, CapValue> capsMap;
+    fill_caps(caps, &capsMap);
+    auto program = this->convertProgram(kind, text, capsMap);
     if (fErrorCount == 0) {
         SkSL::GLSLCodeGenerator cg(&fContext, &caps);
         cg.generateCode(*program.get(), out);