1 /* 2 * Copyright 2016 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #ifndef SKSL_COMPILER 9 #define SKSL_COMPILER 10 11 #include <set> 12 #include <unordered_set> 13 #include <vector> 14 #include "src/sksl/SkSLASTFile.h" 15 #include "src/sksl/SkSLAnalysis.h" 16 #include "src/sksl/SkSLContext.h" 17 #include "src/sksl/SkSLErrorReporter.h" 18 #include "src/sksl/SkSLInliner.h" 19 #include "src/sksl/ir/SkSLProgram.h" 20 #include "src/sksl/ir/SkSLSymbolTable.h" 21 22 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 23 #include "src/gpu/GrShaderVar.h" 24 #endif 25 26 #define SK_FRAGCOLOR_BUILTIN 10001 27 #define SK_IN_BUILTIN 10002 28 #define SK_OUT_BUILTIN 10007 29 #define SK_LASTFRAGCOLOR_BUILTIN 10008 30 #define SK_MAIN_COORDS_BUILTIN 10009 31 #define SK_INPUT_COLOR_BUILTIN 10010 32 #define SK_FRAGCOORD_BUILTIN 15 33 #define SK_CLOCKWISE_BUILTIN 17 34 #define SK_VERTEXID_BUILTIN 42 35 #define SK_INSTANCEID_BUILTIN 43 36 #define SK_INVOCATIONID_BUILTIN 8 37 #define SK_POSITION_BUILTIN 0 38 39 class SkBitSet; 40 class SkSLCompileBench; 41 42 namespace SkSL { 43 44 namespace dsl { 45 class DSLWriter; 46 } 47 48 class ExternalFunction; 49 class FunctionDeclaration; 50 class IRGenerator; 51 class IRIntrinsicMap; 52 class ProgramUsage; 53 54 struct LoadedModule { 55 ProgramKind fKind; 56 std::shared_ptr<SymbolTable> fSymbols; 57 std::vector<std::unique_ptr<ProgramElement>> fElements; 58 }; 59 60 struct ParsedModule { 61 std::shared_ptr<SymbolTable> fSymbols; 62 std::shared_ptr<IRIntrinsicMap> fIntrinsics; 63 }; 64 65 /** 66 * Main compiler entry point. This is a traditional compiler design which first parses the .sksl 67 * file into an abstract syntax tree (a tree of ASTNodes), then performs semantic analysis to 68 * produce a Program (a tree of IRNodes), then feeds the Program into a CodeGenerator to produce 69 * compiled output. 70 * 71 * See the README for information about SkSL. 72 */ 73 class SK_API Compiler : public ErrorReporter { 74 public: 75 static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor"; 76 static constexpr const char RTADJUST_NAME[] = "sk_RTAdjust"; 77 static constexpr const char PERVERTEX_NAME[] = "sk_PerVertex"; 78 79 struct OptimizationContext { 80 // nodes we have already reported errors for and should not error on again 81 std::unordered_set<const IRNode*> fSilences; 82 // true if we have updated the CFG during this pass 83 bool fUpdated = false; 84 // true if we need to completely regenerate the CFG 85 bool fNeedsRescan = false; 86 // Metadata about function and variable usage within the program 87 ProgramUsage* fUsage = nullptr; 88 // Nodes which we can't throw away until the end of optimization 89 StatementArray fOwnedStatements; 90 }; 91 92 Compiler(const ShaderCapsClass* caps); 93 94 ~Compiler() override; 95 96 Compiler(const Compiler&) = delete; 97 Compiler& operator=(const Compiler&) = delete; 98 99 /** 100 * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like 101 * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging. 102 */ 103 enum class OverrideFlag { 104 kDefault, 105 kOff, 106 kOn, 107 }; EnableOptimizer(OverrideFlag flag)108 static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; } EnableInliner(OverrideFlag flag)109 static void EnableInliner(OverrideFlag flag) { sInliner = flag; } 110 111 /** 112 * If externalFunctions is supplied, those values are registered in the symbol table of the 113 * Program, but ownership is *not* transferred. It is up to the caller to keep them alive. 114 */ 115 std::unique_ptr<Program> convertProgram( 116 ProgramKind kind, 117 String text, 118 const Program::Settings& settings, 119 const std::vector<std::unique_ptr<ExternalFunction>>* externalFunctions = nullptr); 120 121 bool toSPIRV(Program& program, OutputStream& out); 122 123 bool toSPIRV(Program& program, String* out); 124 125 bool toGLSL(Program& program, OutputStream& out); 126 127 bool toGLSL(Program& program, String* out); 128 129 bool toHLSL(Program& program, String* out); 130 131 bool toMetal(Program& program, OutputStream& out); 132 133 bool toMetal(Program& program, String* out); 134 135 #if defined(SKSL_STANDALONE) || GR_TEST_UTILS 136 bool toCPP(Program& program, String name, OutputStream& out); 137 138 bool toDSLCPP(Program& program, String name, OutputStream& out); 139 140 bool toH(Program& program, String name, OutputStream& out); 141 #endif 142 143 void error(int offset, String msg) override; 144 145 String errorText(bool showCount = true); 146 147 void writeErrorCount(); 148 errorCount()149 int errorCount() override { 150 return fErrorCount; 151 } 152 153 void setErrorCount(int c) override; 154 context()155 Context& context() { 156 return *fContext; 157 } 158 159 // When SKSL_STANDALONE, fPath is used. (fData, fSize) will be (nullptr, 0) 160 // When !SKSL_STANDALONE, fData and fSize are used. fPath will be nullptr. 161 struct ModuleData { 162 const char* fPath; 163 164 const uint8_t* fData; 165 size_t fSize; 166 }; 167 MakeModulePath(const char * path)168 static ModuleData MakeModulePath(const char* path) { 169 return ModuleData{path, /*fData=*/nullptr, /*fSize=*/0}; 170 } MakeModuleData(const uint8_t * data,size_t size)171 static ModuleData MakeModuleData(const uint8_t* data, size_t size) { 172 return ModuleData{/*fPath=*/nullptr, data, size}; 173 } 174 175 LoadedModule loadModule(ProgramKind kind, ModuleData data, std::shared_ptr<SymbolTable> base, 176 bool dehydrate); 177 ParsedModule parseModule(ProgramKind kind, ModuleData data, const ParsedModule& base); 178 irGenerator()179 IRGenerator& irGenerator() { 180 return *fIRGenerator; 181 } 182 183 const ParsedModule& moduleForProgramKind(ProgramKind kind); 184 185 private: 186 const ParsedModule& loadGPUModule(); 187 const ParsedModule& loadFragmentModule(); 188 const ParsedModule& loadVertexModule(); 189 const ParsedModule& loadFPModule(); 190 const ParsedModule& loadGeometryModule(); 191 const ParsedModule& loadPublicModule(); 192 const ParsedModule& loadRuntimeColorFilterModule(); 193 const ParsedModule& loadRuntimeShaderModule(); 194 195 /** Verifies that @if and @switch statements were actually optimized away. */ 196 void verifyStaticTests(const Program& program); 197 198 /** Optimize every function in the program. */ 199 bool optimize(Program& program); 200 201 /** Optimize the module. */ 202 bool optimize(LoadedModule& module); 203 204 /** Eliminates unused functions from a Program, according to the stats in ProgramUsage. */ 205 bool removeDeadFunctions(Program& program, ProgramUsage* usage); 206 207 /** Eliminates unreferenced variables from a Program, according to the stats in ProgramUsage. */ 208 bool removeDeadGlobalVariables(Program& program, ProgramUsage* usage); 209 bool removeDeadLocalVariables(Program& program, ProgramUsage* usage); 210 211 Position position(int offset); 212 213 std::shared_ptr<Context> fContext; 214 215 std::shared_ptr<SymbolTable> fRootSymbolTable; 216 std::shared_ptr<SymbolTable> fPrivateSymbolTable; 217 218 ParsedModule fRootModule; // Core types 219 220 ParsedModule fPrivateModule; // [Root] + Internal types 221 ParsedModule fGPUModule; // [Private] + GPU intrinsics, helper functions 222 ParsedModule fVertexModule; // [GPU] + Vertex stage decls 223 ParsedModule fFragmentModule; // [GPU] + Fragment stage decls 224 ParsedModule fGeometryModule; // [GPU] + Geometry stage decls 225 ParsedModule fFPModule; // [GPU] + FP features 226 227 ParsedModule fPublicModule; // [Root] + Public features 228 ParsedModule fRuntimeColorFilterModule; // [Public] + Runtime shader decls 229 ParsedModule fRuntimeShaderModule; // [Public] + Runtime color filter decls 230 231 // holds ModifiersPools belonging to the core includes for lifetime purposes 232 ModifiersPool fCoreModifiers; 233 234 Inliner fInliner; 235 std::unique_ptr<IRGenerator> fIRGenerator; 236 237 const String* fSource = nullptr; 238 int fErrorCount = 0; 239 String fErrorText; 240 std::vector<size_t> fErrorTextLength; 241 242 static OverrideFlag sOptimizer; 243 static OverrideFlag sInliner; 244 245 friend class AutoSource; 246 friend class ::SkSLCompileBench; 247 friend class dsl::DSLWriter; 248 }; 249 250 } // namespace SkSL 251 252 #endif 253