blob: 9f4e3ba44577aac8548c3076922e52f34ce882e2 [file] [log] [blame]
Ethan Nicholas95046142021-01-07 10:57:27 -05001/*
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
Ethan Nicholasdaed2592021-03-04 14:30:25 -050011#include "include/private/SkSLModifiers.h"
Ethan Nicholas24c17722021-03-09 13:10:59 -050012#include "include/private/SkSLStatement.h"
Ethan Nicholasdaed2592021-03-04 14:30:25 -050013#include "include/sksl/DSLExpression.h"
14#include "include/sksl/DSLStatement.h"
Ethan Nicholasbffe80a2021-01-11 15:42:44 -050015#include "src/sksl/SkSLMangler.h"
John Stiles45990502021-02-16 10:55:27 -050016#include "src/sksl/SkSLOperators.h"
Ethan Nicholas55a63af2021-05-18 10:12:58 -040017#include "src/sksl/SkSLParsedModule.h"
Ethan Nicholas95046142021-01-07 10:57:27 -050018#include "src/sksl/ir/SkSLExpressionStatement.h"
19#include "src/sksl/ir/SkSLProgram.h"
Ethan Nicholas95046142021-01-07 10:57:27 -050020#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
21#include "src/gpu/glsl/GrGLSLFragmentProcessor.h"
22#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
John Stiles3befaf22021-04-23 14:42:22 -040023#include <list>
Ethan Nicholas95046142021-01-07 10:57:27 -050024#include <stack>
25
26class AutoDSLContext;
27
28namespace SkSL {
29
30class Compiler;
31class Context;
32class IRGenerator;
Ethan Nicholasdaed2592021-03-04 14:30:25 -050033class ProgramElement;
Ethan Nicholas95046142021-01-07 10:57:27 -050034class SymbolTable;
35class Type;
Ethan Nicholasdaed2592021-03-04 14:30:25 -050036class Variable;
Ethan Nicholas95046142021-01-07 10:57:27 -050037
38namespace dsl {
39
40class ErrorHandler;
41
42/**
43 * Thread-safe class that tracks per-thread state associated with DSL output. This class is for
44 * internal use only.
45 */
46class DSLWriter {
47public:
Ethan Nicholas55a63af2021-05-18 10:12:58 -040048 DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind,
49 const SkSL::ProgramSettings& settings, SkSL::ParsedModule module, bool isModule);
Ethan Nicholas95046142021-01-07 10:57:27 -050050
Ethan Nicholas0584ac02021-02-17 10:48:14 -050051 ~DSLWriter();
52
Ethan Nicholas95046142021-01-07 10:57:27 -050053 /**
54 * Returns the Compiler used by DSL operations in the current thread.
55 */
56 static SkSL::Compiler& Compiler() {
57 return *Instance().fCompiler;
58 }
59
60 /**
61 * Returns the IRGenerator used by DSL operations in the current thread.
62 */
63 static SkSL::IRGenerator& IRGenerator();
64
65 /**
66 * Returns the Context used by DSL operations in the current thread.
67 */
68 static const SkSL::Context& Context();
69
70 /**
Ethan Nicholas1ff76092021-01-28 10:02:43 -050071 * Returns the collection to which DSL program elements in this thread should be appended.
72 */
73 static std::vector<std::unique_ptr<SkSL::ProgramElement>>& ProgramElements() {
74 return Instance().fProgramElements;
75 }
76
Ethan Nicholas55a63af2021-05-18 10:12:58 -040077 static std::vector<const ProgramElement*>& SharedElements() {
78 return Instance().fSharedElements;
79 }
80
Ethan Nicholas1ff76092021-01-28 10:02:43 -050081 /**
Ethan Nicholas95046142021-01-07 10:57:27 -050082 * Returns the SymbolTable of the current thread's IRGenerator.
83 */
84 static const std::shared_ptr<SkSL::SymbolTable>& SymbolTable();
85
Ethan Nicholas55a63af2021-05-18 10:12:58 -040086 /**
87 * Returns the current memory pool.
88 */
89 static std::unique_ptr<Pool>& MemoryPool() { return Instance().fPool; }
90
91 /**
92 * Returns the current modifiers pool.
93 */
94 static std::unique_ptr<ModifiersPool>& GetModifiersPool() { return Instance().fModifiersPool; }
95
96 /**
97 * Returns the current ProgramConfig.
98 */
99 static std::unique_ptr<ProgramConfig>& GetProgramConfig() { return Instance().fConfig; }
100
Ethan Nicholasfe5d6922021-03-05 14:23:48 -0500101 static void Reset();
102
Ethan Nicholas95046142021-01-07 10:57:27 -0500103 /**
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500104 * Returns the final pointer to a pooled Modifiers object that should be used to represent the
105 * given modifiers.
106 */
John Stilesf2872e62021-05-04 11:38:43 -0400107 static const SkSL::Modifiers* Modifiers(const SkSL::Modifiers& modifiers);
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500108
109 /**
Ethan Nicholas371f6e12021-05-04 14:30:02 -0400110 * Returns the SkSL variable corresponding to a (non-parameter) DSLVar.
Ethan Nicholasd6b26e52021-01-27 07:53:46 -0500111 */
Ethan Nicholasb4f8b7a2021-06-23 10:27:09 -0400112 static const SkSL::Variable* Var(DSLVar& var);
Ethan Nicholas707d3152021-03-25 17:49:08 -0400113
114 /**
Ethan Nicholas371f6e12021-05-04 14:30:02 -0400115 * Creates an SkSL variable corresponding to a parameter DSLVar.
116 */
117 static std::unique_ptr<SkSL::Variable> ParameterVar(DSLVar& var);
118
119 /**
Ethan Nicholas707d3152021-03-25 17:49:08 -0400120 * Returns the SkSL declaration corresponding to a DSLVar.
121 */
122 static std::unique_ptr<SkSL::Statement> Declaration(DSLVar& var);
Ethan Nicholasd6b26e52021-01-27 07:53:46 -0500123
124 /**
Ethan Nicholas961d9442021-03-16 16:37:29 -0400125 * For use in testing only: marks the variable as having been declared, so that it can be
126 * destroyed without generating errors.
127 */
128 static void MarkDeclared(DSLVar& var);
129
130 /**
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500131 * Returns the (possibly mangled) final name that should be used for an entity with the given
132 * raw name.
133 */
134 static const char* Name(const char* name);
135
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500136#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
137 /**
138 * Returns the fragment processor for which DSL output is being generated for the current
139 * thread.
140 */
141 static GrGLSLFragmentProcessor* CurrentProcessor() {
142 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
143 return Instance().fStack.top().fProcessor;
144 }
145
146 /**
147 * Returns the EmitArgs for fragment processor output in the current thread.
148 */
149 static GrGLSLFragmentProcessor::EmitArgs* CurrentEmitArgs() {
150 SkASSERTF(!Instance().fStack.empty(), "This feature requires a FragmentProcessor");
151 return Instance().fStack.top().fEmitArgs;
152 }
153
Ethan Nicholas11a15b12021-02-11 15:56:27 -0500154 static bool InFragmentProcessor() {
155 return !Instance().fStack.empty();
156 }
157
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500158 /**
159 * Pushes a new processor / emitArgs pair for the current thread.
160 */
161 static void StartFragmentProcessor(GrGLSLFragmentProcessor* processor,
162 GrGLSLFragmentProcessor::EmitArgs* emitArgs);
163
164 /**
165 * Pops the processor / emitArgs pair associated with the current thread.
166 */
167 static void EndFragmentProcessor();
Ethan Nicholas11a15b12021-02-11 15:56:27 -0500168
169 static GrGLSLUniformHandler::UniformHandle VarUniformHandle(const DSLVar& var);
Ethan Nicholasee49efc2021-04-09 15:33:53 -0400170#else
171 static bool InFragmentProcessor() {
172 return false;
173 }
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500174#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
175
Ethan Nicholasdaed2592021-03-04 14:30:25 -0500176 static std::unique_ptr<SkSL::Expression> Call(const FunctionDeclaration& function,
177 ExpressionArray arguments);
178
Ethan Nicholas1ff76092021-01-28 10:02:43 -0500179 /**
Ethan Nicholas722cb672021-05-06 10:47:06 -0400180 * Invokes expr(arguments), where expr is a function or type reference.
181 */
182 static std::unique_ptr<SkSL::Expression> Call(std::unique_ptr<SkSL::Expression> expr,
183 ExpressionArray arguments);
184
Ethan Nicholasb4f8b7a2021-06-23 10:27:09 -0400185 static DSLPossibleExpression Coerce(std::unique_ptr<Expression> expr, const SkSL::Type& type);
Ethan Nicholas92969f22021-01-13 10:38:59 -0500186
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500187 static DSLPossibleExpression Construct(const SkSL::Type& type,
Ethan Nicholas84558932021-04-12 16:56:37 -0400188 SkTArray<DSLExpression> rawArgs);
Ethan Nicholasb3d4e742021-01-08 11:42:25 -0500189
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500190 static std::unique_ptr<Expression> ConvertBinary(std::unique_ptr<Expression> left, Operator op,
191 std::unique_ptr<Expression> right);
Ethan Nicholasbf79dff2021-02-11 15:18:31 -0500192
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500193 static std::unique_ptr<SkSL::Expression> ConvertField(std::unique_ptr<Expression> base,
194 const char* name);
Ethan Nicholas92969f22021-01-13 10:38:59 -0500195
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500196 static std::unique_ptr<Expression> ConvertIndex(std::unique_ptr<Expression> base,
197 std::unique_ptr<Expression> index);
Ethan Nicholas92969f22021-01-13 10:38:59 -0500198
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500199 static std::unique_ptr<Expression> ConvertPostfix(std::unique_ptr<Expression> expr,
200 Operator op);
Ethan Nicholas92969f22021-01-13 10:38:59 -0500201
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500202 static std::unique_ptr<Expression> ConvertPrefix(Operator op, std::unique_ptr<Expression> expr);
Ethan Nicholas92969f22021-01-13 10:38:59 -0500203
Ethan Nicholas34c7e112021-02-25 20:50:32 -0500204 static DSLPossibleStatement ConvertSwitch(std::unique_ptr<Expression> value,
205 ExpressionArray caseValues,
Ethan Nicholas8a6537d2021-04-30 12:44:00 -0400206 SkTArray<SkSL::StatementArray> caseStatements,
207 bool isStatic);
Ethan Nicholascfefec02021-02-09 15:22:57 -0500208
Ethan Nicholas95046142021-01-07 10:57:27 -0500209 /**
210 * Sets the ErrorHandler associated with the current thread. This object will be notified when
211 * any DSL errors occur. With a null ErrorHandler (the default), any errors will be dumped to
212 * stderr and a fatal exception will be generated.
213 */
214 static void SetErrorHandler(ErrorHandler* errorHandler) {
215 Instance().fErrorHandler = errorHandler;
216 }
217
218 /**
219 * Notifies the current ErrorHandler that a DSL error has occurred. With a null ErrorHandler
220 * (the default), any errors will be dumped to stderr and a fatal exception will be generated.
221 */
Ethan Nicholasb9563042021-02-25 09:45:49 -0500222 static void ReportError(const char* msg, PositionInfo* info = nullptr);
Ethan Nicholas95046142021-01-07 10:57:27 -0500223
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500224 /**
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400225 * Returns whether name mangling is enabled. Mangling is important for the DSL because its
226 * variables normally all go into the same symbol table; for instance if you were to translate
227 * this legal (albeit silly) GLSL code:
228 * int x;
229 * {
230 * int x;
231 * }
232 *
233 * into DSL, you'd end up with:
234 * DSLVar x1(kInt_Type, "x");
235 * DSLVar x2(kInt_Type, "x");
236 * Declare(x1);
237 * Block(Declare(x2));
238 *
239 * with x1 and x2 ending up in the same symbol table. This is fine as long as their effective
240 * names are different, so mangling prevents this situation from causing problems.
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500241 */
242 static bool ManglingEnabled() {
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400243 return Instance().fSettings.fDSLMangling;
244 }
245
246 /**
247 * Returns whether DSLVars should automatically be marked declared upon creation. This is used
248 * to simplify testing.
249 */
250 static bool MarkVarsDeclared() {
251 return Instance().fSettings.fDSLMarkVarsDeclared;
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500252 }
253
Ethan Nicholasb4f8b7a2021-06-23 10:27:09 -0400254 /**
255 * Forwards any pending Compiler errors to the DSL ErrorHandler.
256 */
257 static void ReportErrors(PositionInfo pos = PositionInfo());
258
Ethan Nicholas95046142021-01-07 10:57:27 -0500259 static DSLWriter& Instance();
260
261 static void SetInstance(std::unique_ptr<DSLWriter> instance);
262
263private:
Ethan Nicholas624a5292021-04-16 14:54:43 -0400264 std::unique_ptr<SkSL::ProgramConfig> fConfig;
John Stiles10d39d92021-05-04 16:13:14 -0400265 std::unique_ptr<SkSL::ModifiersPool> fModifiersPool;
Ethan Nicholas95046142021-01-07 10:57:27 -0500266 SkSL::Compiler* fCompiler;
Ethan Nicholas961d9442021-03-16 16:37:29 -0400267 std::unique_ptr<Pool> fPool;
John Stilesd1204642021-02-17 16:30:02 -0500268 SkSL::ProgramConfig* fOldConfig;
John Stiles10d39d92021-05-04 16:13:14 -0400269 SkSL::ModifiersPool* fOldModifiersPool;
Ethan Nicholas1ff76092021-01-28 10:02:43 -0500270 std::vector<std::unique_ptr<SkSL::ProgramElement>> fProgramElements;
Ethan Nicholas624a5292021-04-16 14:54:43 -0400271 std::vector<const SkSL::ProgramElement*> fSharedElements;
Ethan Nicholas95046142021-01-07 10:57:27 -0500272 ErrorHandler* fErrorHandler = nullptr;
Ethan Nicholas55a63af2021-05-18 10:12:58 -0400273 ProgramSettings fSettings;
Ethan Nicholasbffe80a2021-01-11 15:42:44 -0500274 Mangler fMangler;
Ethan Nicholas4f3e6a22021-06-15 09:17:05 -0400275 bool fEncounteredErrors = false;
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500276#if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
277 struct StackFrame {
278 GrGLSLFragmentProcessor* fProcessor;
279 GrGLSLFragmentProcessor::EmitArgs* fEmitArgs;
John Stiles3befaf22021-04-23 14:42:22 -0400280 SkSL::StatementArray fSavedDeclarations;
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500281 };
John Stiles3befaf22021-04-23 14:42:22 -0400282 std::stack<StackFrame, std::list<StackFrame>> fStack;
Ethan Nicholasc3bb9e32021-02-02 11:51:03 -0500283#endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
Ethan Nicholas95046142021-01-07 10:57:27 -0500284
285 friend class DSLCore;
Ethan Nicholas961d9442021-03-16 16:37:29 -0400286 friend class DSLVar;
Ethan Nicholas95046142021-01-07 10:57:27 -0500287};
288
289} // namespace dsl
290
291} // namespace SkSL
292
293#endif