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 "include/core/SkSize.h" 12 #include "include/core/SkTypes.h" 13 #include "src/sksl/SkSLContext.h" // IWYU pragma: keep 14 #include "src/sksl/SkSLErrorReporter.h" 15 #include "src/sksl/SkSLPosition.h" 16 17 #include <array> 18 #include <cstdint> 19 #include <memory> 20 #include <string> 21 #include <string_view> 22 #include <type_traits> 23 #include <vector> 24 25 constexpr int SK_FRAGCOLOR_BUILTIN = 10001; 26 constexpr int SK_LASTFRAGCOLOR_BUILTIN = 10008; 27 constexpr int SK_SECONDARYFRAGCOLOR_BUILTIN = 10012; 28 constexpr int SK_FRAGCOORD_BUILTIN = 15; 29 constexpr int SK_CLOCKWISE_BUILTIN = 17; 30 constexpr int SK_SAMPLEMASKIN_BUILTIN = 20; 31 constexpr int SK_SAMPLEMASK_BUILTIN = 10020; 32 33 constexpr int SK_VERTEXID_BUILTIN = 42; 34 constexpr int SK_INSTANCEID_BUILTIN = 43; 35 constexpr int SK_POSITION_BUILTIN = 0; 36 constexpr int SK_POINTSIZE_BUILTIN = 1; 37 38 constexpr int SK_NUMWORKGROUPS_BUILTIN = 24; 39 constexpr int SK_WORKGROUPID_BUILTIN = 26; 40 constexpr int SK_LOCALINVOCATIONID_BUILTIN = 27; 41 constexpr int SK_GLOBALINVOCATIONID_BUILTIN = 28; 42 constexpr int SK_LOCALINVOCATIONINDEX_BUILTIN = 29; 43 44 namespace SkSL { 45 46 class Inliner; 47 struct Module; 48 enum class ModuleType : int8_t; 49 class Pool; 50 struct ProgramConfig; 51 class ProgramUsage; 52 enum class ProgramKind : int8_t; 53 struct Program; 54 class ProgramElement; 55 struct ProgramSettings; 56 class SymbolTable; 57 58 /** 59 * Main compiler entry point. The compiler parses the SkSL text directly into a tree of IRNodes, 60 * while performing basic optimizations such as constant-folding and dead-code elimination. Then the 61 * Program is passed into a CodeGenerator to produce compiled output. 62 * 63 * See the README for information about SkSL. 64 */ 65 class SK_API Compiler { 66 public: 67 inline static constexpr const char FRAGCOLOR_NAME[] = "sk_FragColor"; 68 inline static constexpr const char RTADJUST_NAME[] = "sk_RTAdjust"; 69 inline static constexpr const char POSITION_NAME[] = "sk_Position"; 70 inline static constexpr const char POISON_TAG[] = "<POISON>"; 71 72 /** 73 * Gets a float4 that adjusts the position from Skia device coords to normalized device coords, 74 * used to populate sk_RTAdjust. Assuming the transformed position, pos, is a homogeneous 75 * float4, the vec, v, is applied as such: 76 * float4((pos.xy * v.xz) + sk_Position.ww * v.yw, 0, pos.w); 77 */ GetRTAdjustVector(SkISize rtDims,bool flipY)78 static std::array<float, 4> GetRTAdjustVector(SkISize rtDims, bool flipY) { 79 std::array<float, 4> result; 80 result[0] = 2.f/rtDims.width(); 81 result[2] = 2.f/rtDims.height(); 82 result[1] = -1.f; 83 result[3] = -1.f; 84 if (flipY) { 85 result[2] = -result[2]; 86 result[3] = -result[3]; 87 } 88 return result; 89 } 90 91 /** 92 * Uniform values used by the compiler to implement origin-neutral dFdy, sk_Clockwise, and 93 * sk_FragCoord. 94 */ GetRTFlipVector(int rtHeight,bool flipY)95 static std::array<float, 2> GetRTFlipVector(int rtHeight, bool flipY) { 96 std::array<float, 2> result; 97 result[0] = flipY ? rtHeight : 0.f; 98 result[1] = flipY ? -1.f : 1.f; 99 return result; 100 } 101 102 Compiler(); 103 ~Compiler(); 104 105 Compiler(const Compiler&) = delete; 106 Compiler& operator=(const Compiler&) = delete; 107 108 /** 109 * Allows optimization settings to be unilaterally overridden. This is meant to allow tools like 110 * Viewer or Nanobench to override the compiler's ProgramSettings and ShaderCaps for debugging. 111 */ 112 enum class OverrideFlag { 113 kDefault, 114 kOff, 115 kOn, 116 }; EnableOptimizer(OverrideFlag flag)117 static void EnableOptimizer(OverrideFlag flag) { sOptimizer = flag; } EnableInliner(OverrideFlag flag)118 static void EnableInliner(OverrideFlag flag) { sInliner = flag; } 119 120 std::unique_ptr<Program> convertProgram(ProgramKind kind, 121 std::string programSource, 122 const ProgramSettings& settings); 123 124 void handleError(std::string_view msg, Position pos); 125 126 std::string errorText(bool showCount = true); 127 errorReporter()128 ErrorReporter& errorReporter() { return *fContext->fErrors; } 129 errorCount()130 int errorCount() const { return fContext->fErrors->errorCount(); } 131 132 void writeErrorCount(); 133 resetErrors()134 void resetErrors() { 135 fErrorText.clear(); 136 this->errorReporter().resetErrorCount(); 137 } 138 context()139 Context& context() const { 140 return *fContext; 141 } 142 globalSymbols()143 SymbolTable* globalSymbols() { 144 return fGlobalSymbols.get(); 145 } 146 symbolTable()147 SymbolTable* symbolTable() { 148 return fContext->fSymbolTable; 149 } 150 151 std::unique_ptr<Module> compileModule(ProgramKind kind, 152 ModuleType moduleType, 153 std::string moduleSource, 154 const Module* parentModule, 155 bool shouldInline); 156 157 /** Optimize a module at minification time, before writing it out. */ 158 bool optimizeModuleBeforeMinifying(ProgramKind kind, Module& module, bool shrinkSymbols); 159 160 const Module* moduleForProgramKind(ProgramKind kind); 161 162 /** Run the inliner on a program which was compiled earlier (with inlining turned off). */ 163 void runInliner(Program& program); 164 165 private: 166 class CompilerErrorReporter : public ErrorReporter { 167 public: CompilerErrorReporter(Compiler * compiler)168 CompilerErrorReporter(Compiler* compiler) 169 : fCompiler(*compiler) {} 170 handleError(std::string_view msg,Position pos)171 void handleError(std::string_view msg, Position pos) override { 172 fCompiler.handleError(msg, pos); 173 } 174 175 private: 176 Compiler& fCompiler; 177 }; 178 179 /** Updates ProgramSettings to eliminate contradictions and to honor the ProgramKind. */ 180 static void FinalizeSettings(ProgramSettings* settings, ProgramKind kind); 181 182 /** Prepares the Context for compilation of a program or module. */ 183 void initializeContext(const SkSL::Module* module, 184 ProgramKind kind, 185 ProgramSettings settings, 186 std::string_view source, 187 ModuleType moduleType); 188 189 /** Cleans up the Context post-compilation. */ 190 void cleanupContext(); 191 192 /** 193 * Returns all global elements (functions and global variables) as a self-contained Program. 194 * The optional source string is retained as the program's source. 195 */ 196 std::unique_ptr<SkSL::Program> releaseProgram( 197 std::unique_ptr<std::string> source, 198 std::vector<std::unique_ptr<SkSL::ProgramElement>> programElements); 199 200 /** Optimize every function in the program. */ 201 bool optimize(Program& program); 202 203 /** Performs final checks to confirm that a fully-assembled/optimized is valid. */ 204 bool finalize(Program& program); 205 206 /** Optimize a module at Skia runtime, after loading it. */ 207 bool optimizeModuleAfterLoading(ProgramKind kind, Module& module); 208 209 /** Flattens out function calls when it is safe to do so. */ 210 bool runInliner(Inliner* inliner, 211 const std::vector<std::unique_ptr<ProgramElement>>& elements, 212 SymbolTable* symbols, 213 ProgramUsage* usage); 214 215 CompilerErrorReporter fErrorReporter; 216 std::shared_ptr<Context> fContext; 217 std::unique_ptr<SymbolTable> fGlobalSymbols; 218 std::unique_ptr<ProgramConfig> fConfig; 219 std::unique_ptr<Pool> fPool; 220 221 std::string fErrorText; 222 223 static OverrideFlag sOptimizer; 224 static OverrideFlag sInliner; 225 226 friend class Parser; 227 friend class ThreadContext; 228 }; 229 230 } // namespace SkSL 231 232 #endif 233