1 /* 2 * Copyright 2020 Google LLC 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_DSLWRITER 9 #define SKSL_DSLWRITER 10 11 #include "include/private/SkSLModifiers.h" 12 #include "include/private/SkSLStatement.h" 13 #include "include/sksl/DSLExpression.h" 14 #include "include/sksl/DSLStatement.h" 15 #include "src/sksl/SkSLMangler.h" 16 #include "src/sksl/SkSLOperators.h" 17 #include "src/sksl/ir/SkSLExpressionStatement.h" 18 #include "src/sksl/ir/SkSLProgram.h" 19 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 20 #include "src/gpu/glsl/GrGLSLFragmentProcessor.h" 21 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 22 #include <list> 23 #include <stack> 24 25 class AutoDSLContext; 26 27 namespace SkSL { 28 29 class Compiler; 30 class Context; 31 class IRGenerator; 32 class ProgramElement; 33 class SymbolTable; 34 class Type; 35 class Variable; 36 37 namespace dsl { 38 39 class ErrorHandler; 40 41 /** 42 * Thread-safe class that tracks per-thread state associated with DSL output. This class is for 43 * internal use only. 44 */ 45 class DSLWriter { 46 public: 47 DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind, int flags); 48 49 ~DSLWriter(); 50 51 /** 52 * Returns the Compiler used by DSL operations in the current thread. 53 */ Compiler()54 static SkSL::Compiler& Compiler() { 55 return *Instance().fCompiler; 56 } 57 58 /** 59 * Returns the IRGenerator used by DSL operations in the current thread. 60 */ 61 static SkSL::IRGenerator& IRGenerator(); 62 63 /** 64 * Returns the Context used by DSL operations in the current thread. 65 */ 66 static const SkSL::Context& Context(); 67 68 /** 69 * Returns the collection to which DSL program elements in this thread should be appended. 70 */ ProgramElements()71 static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() { 72 return Instance().fProgramElements; 73 } 74 75 /** 76 * Returns the SymbolTable of the current thread's IRGenerator. 77 */ 78 static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable(); 79 80 static void Reset(); 81 82 /** 83 * Returns the final pointer to a pooled Modifiers object that should be used to represent the 84 * given modifiers. 85 */ 86 static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers); 87 88 /** 89 * Returns the SkSL variable corresponding to a (non-parameter) DSLVar. 90 */ 91 static const SkSL::Variable& Var(DSLVar& var); 92 93 /** 94 * Creates an SkSL variable corresponding to a parameter DSLVar. 95 */ 96 static std::unique_ptr<SkSL::Variable> ParameterVar(DSLVar& var); 97 98 /** 99 * Returns the SkSL declaration corresponding to a DSLVar. 100 */ 101 static std::unique_ptr<SkSL::Statement> Declaration(DSLVar& var); 102 103 /** 104 * For use in testing only: marks the variable as having been declared, so that it can be 105 * destroyed without generating errors. 106 */ 107 static void MarkDeclared(DSLVar& var); 108 109 /** 110 * Returns the (possibly mangled) final name that should be used for an entity with the given 111 * raw name. 112 */ 113 static const char* Name(const char* name); 114 115 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 116 /** 117 * Returns the fragment processor for which DSL output is being generated for the current 118 * thread. 119 */ CurrentProcessor()120 static GrGLSLFragmentProcessor* CurrentProcessor() { 121 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor"); 122 return Instance().fStack.top().fProcessor; 123 } 124 125 /** 126 * Returns the EmitArgs for fragment processor output in the current thread. 127 */ CurrentEmitArgs()128 static GrGLSLFragmentProcessor::EmitArgs* CurrentEmitArgs() { 129 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor"); 130 return Instance().fStack.top().fEmitArgs; 131 } 132 InFragmentProcessor()133 static bool InFragmentProcessor() { 134 return !Instance().fStack.empty(); 135 } 136 137 /** 138 * Pushes a new processor / emitArgs pair for the current thread. 139 */ 140 static void StartFragmentProcessor(GrGLSLFragmentProcessor* processor, 141 GrGLSLFragmentProcessor::EmitArgs* emitArgs); 142 143 /** 144 * Pops the processor / emitArgs pair associated with the current thread. 145 */ 146 static void EndFragmentProcessor(); 147 148 static GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLVar& var); 149 #else InFragmentProcessor()150 static bool InFragmentProcessor() { 151 return false; 152 } 153 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 154 155 static std::unique_ptr<SkSL::Expression> Call(const FunctionDeclaration& function, 156 ExpressionArray arguments); 157 158 /** 159 * Invokes expr(arguments), where expr is a function or type reference. 160 */ 161 static std::unique_ptr<SkSL::Expression> Call(std::unique_ptr<SkSL::Expression> expr, 162 ExpressionArray arguments); 163 164 /** 165 * Reports an error if the argument is null. Returns its argument unmodified. 166 */ 167 static std::unique_ptr<SkSL::Expression> Check(std::unique_ptr<SkSL::Expression> expr); 168 169 static DSLPossibleExpression Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type); 170 171 static DSLPossibleExpression Construct(const SkSL::Type& type, 172 SkTArray<DSLExpression> rawArgs); 173 174 static std::unique_ptr<Expression> ConvertBinary(std::unique_ptr<Expression> left, Operator op, 175 std::unique_ptr<Expression> right); 176 177 static std::unique_ptr<SkSL::Expression> ConvertField(std::unique_ptr<Expression> base, 178 const char* name); 179 180 static std::unique_ptr<Expression> ConvertIndex(std::unique_ptr<Expression> base, 181 std::unique_ptr<Expression> index); 182 183 static std::unique_ptr<Expression> ConvertPostfix(std::unique_ptr<Expression> expr, 184 Operator op); 185 186 static std::unique_ptr<Expression> ConvertPrefix(Operator op, std::unique_ptr<Expression> expr); 187 188 static DSLPossibleStatement ConvertSwitch(std::unique_ptr<Expression> value, 189 ExpressionArray caseValues, 190 SkTArray<SkSL::StatementArray> caseStatements, 191 bool isStatic); 192 193 /** 194 * Sets the ErrorHandler associated with the current thread. This object will be notified when 195 * any DSL errors occur. With a null ErrorHandler (the default), any errors will be dumped to 196 * stderr and a fatal exception will be generated. 197 */ SetErrorHandler(ErrorHandler * errorHandler)198 static void SetErrorHandler(ErrorHandler* errorHandler) { 199 Instance().fErrorHandler = errorHandler; 200 } 201 202 /** 203 * Notifies the current ErrorHandler that a DSL error has occurred. With a null ErrorHandler 204 * (the default), any errors will be dumped to stderr and a fatal exception will be generated. 205 */ 206 static void ReportError(const char* msg, PositionInfo* info = nullptr); 207 208 /** 209 * Returns whether name mangling is enabled. This should always be enabled outside of tests. 210 */ ManglingEnabled()211 static bool ManglingEnabled() { 212 return Instance().fMangle; 213 } 214 215 static std::unique_ptr<SkSL::Program> ReleaseProgram(); 216 217 static DSLWriter& Instance(); 218 219 static void SetInstance(std::unique_ptr<DSLWriter> instance); 220 221 private: 222 std::unique_ptr<SkSL::ProgramConfig> fConfig; 223 std::unique_ptr<SkSL::ModifiersPool> fModifiersPool; 224 SkSL::Compiler* fCompiler; 225 std::unique_ptr<Pool> fPool; 226 SkSL::ProgramConfig* fOldConfig; 227 SkSL::ModifiersPool* fOldModifiersPool; 228 std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements; 229 std::vector<const SkSL::ProgramElement*> fSharedElements; 230 ErrorHandler* fErrorHandler = nullptr; 231 bool fMangle = true; 232 bool fMarkVarsDeclared = false; 233 Mangler fMangler; 234 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 235 struct StackFrame { 236 GrGLSLFragmentProcessor* fProcessor; 237 GrGLSLFragmentProcessor::EmitArgs* fEmitArgs; 238 SkSL::StatementArray fSavedDeclarations; 239 }; 240 std::stack<StackFrame, std::list<StackFrame>> fStack; 241 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU 242 243 friend class DSLCore; 244 friend class DSLVar; 245 }; 246 247 } // namespace dsl 248 249 } // namespace SkSL 250 251 #endif 252