• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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