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 #include "src/sksl/dsl/priv/DSLWriter.h"
9
10 #include "include/private/SkSLDefines.h"
11 #include "include/sksl/DSLCore.h"
12 #include "include/sksl/DSLErrorHandling.h"
13 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
14 #include "src/gpu/glsl/GrGLSLFragmentShaderBuilder.h"
15 #include "src/gpu/mock/GrMockCaps.h"
16 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
17 #include "src/sksl/SkSLCompiler.h"
18 #include "src/sksl/SkSLIRGenerator.h"
19 #include "src/sksl/ir/SkSLBinaryExpression.h"
20 #include "src/sksl/ir/SkSLBlock.h"
21 #include "src/sksl/ir/SkSLConstructor.h"
22 #include "src/sksl/ir/SkSLPostfixExpression.h"
23 #include "src/sksl/ir/SkSLPrefixExpression.h"
24 #include "src/sksl/ir/SkSLSwitchStatement.h"
25
26 #if !SKSL_USE_THREAD_LOCAL
27 #include <pthread.h>
28 #endif // !SKSL_USE_THREAD_LOCAL
29
30 namespace SkSL {
31
32 namespace dsl {
33
DSLWriter(SkSL::Compiler * compiler,SkSL::ProgramKind kind,int flags)34 DSLWriter::DSLWriter(SkSL::Compiler* compiler, SkSL::ProgramKind kind, int flags)
35 : fCompiler(compiler)
36 , fMangle(flags & kMangle_Flag)
37 , fMarkVarsDeclared(flags & kMarkVarsDeclared_Flag) {
38 SkSL::ParsedModule module = fCompiler->moduleForProgramKind(kind);
39
40 fModifiersPool = std::make_unique<ModifiersPool>();
41 fOldModifiersPool = fCompiler->fContext->fModifiersPool;
42 fCompiler->fContext->fModifiersPool = fModifiersPool.get();
43
44 fConfig = std::make_unique<ProgramConfig>();
45 fConfig->fKind = kind;
46 fConfig->fSettings.fOptimize = flags & kOptimize_Flag;
47 fConfig->fSettings.fValidateSPIRV = flags & kValidate_Flag;
48 fOldConfig = fCompiler->fContext->fConfig;
49 fCompiler->fContext->fConfig = fConfig.get();
50
51 if (compiler->context().fCaps.useNodePools()) {
52 fPool = Pool::Create();
53 fPool->attachToThread();
54 }
55
56 fCompiler->fIRGenerator->start(module, /*isBuiltinCode=*/false, /*externalFunctions=*/nullptr,
57 &fProgramElements, &fSharedElements);
58 }
59
~DSLWriter()60 DSLWriter::~DSLWriter() {
61 if (SymbolTable()) {
62 fCompiler->fIRGenerator->finish();
63 fProgramElements.clear();
64 } else {
65 // We should only be here with a null symbol table if ReleaseProgram was called
66 SkASSERT(fProgramElements.empty());
67 }
68 fCompiler->fContext->fConfig = fOldConfig;
69 fCompiler->fContext->fModifiersPool = fOldModifiersPool;
70 if (fPool) {
71 fPool->detachFromThread();
72 }
73 }
74
IRGenerator()75 SkSL::IRGenerator& DSLWriter::IRGenerator() {
76 return *Compiler().fIRGenerator;
77 }
78
Context()79 const SkSL::Context& DSLWriter::Context() {
80 return IRGenerator().fContext;
81 }
82
SymbolTable()83 const std::shared_ptr<SkSL::SymbolTable>& DSLWriter::SymbolTable() {
84 return IRGenerator().fSymbolTable;
85 }
86
Reset()87 void DSLWriter::Reset() {
88 IRGenerator().popSymbolTable();
89 IRGenerator().pushSymbolTable();
90 ProgramElements().clear();
91 Instance().fModifiersPool->clear();
92 }
93
Modifiers(const SkSL::Modifiers & modifiers)94 const SkSL::Modifiers* DSLWriter::Modifiers(const SkSL::Modifiers& modifiers) {
95 return Context().fModifiersPool->add(modifiers);
96 }
97
Name(const char * name)98 const char* DSLWriter::Name(const char* name) {
99 if (ManglingEnabled()) {
100 const String* s = SymbolTable()->takeOwnershipOfString(
101 Instance().fMangler.uniqueName(name, SymbolTable().get()));
102 return s->c_str();
103 }
104 return name;
105 }
106
107 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
StartFragmentProcessor(GrGLSLFragmentProcessor * processor,GrGLSLFragmentProcessor::EmitArgs * emitArgs)108 void DSLWriter::StartFragmentProcessor(GrGLSLFragmentProcessor* processor,
109 GrGLSLFragmentProcessor::EmitArgs* emitArgs) {
110 DSLWriter& instance = Instance();
111 instance.fStack.push({processor, emitArgs, StatementArray{}});
112 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
113 IRGenerator().pushSymbolTable();
114 }
115
EndFragmentProcessor()116 void DSLWriter::EndFragmentProcessor() {
117 DSLWriter& instance = Instance();
118 SkASSERT(!instance.fStack.empty());
119 CurrentEmitArgs()->fFragBuilder->fDeclarations.swap(instance.fStack.top().fSavedDeclarations);
120 instance.fStack.pop();
121 IRGenerator().popSymbolTable();
122 }
123
VarUniformHandle(const DSLVar & var)124 GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLVar& var) {
125 return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
126 }
127 #endif // !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
128
Call(const FunctionDeclaration & function,ExpressionArray arguments)129 std::unique_ptr<SkSL::Expression> DSLWriter::Call(const FunctionDeclaration& function,
130 ExpressionArray arguments) {
131 // We can't call FunctionCall::Convert directly here, because intrinsic management is handled in
132 // IRGenerator::call.
133 return IRGenerator().call(/*offset=*/-1, function, std::move(arguments));
134 }
135
Call(std::unique_ptr<SkSL::Expression> expr,ExpressionArray arguments)136 std::unique_ptr<SkSL::Expression> DSLWriter::Call(std::unique_ptr<SkSL::Expression> expr,
137 ExpressionArray arguments) {
138 // We can't call FunctionCall::Convert directly here, because intrinsic management is handled in
139 // IRGenerator::call.
140 return IRGenerator().call(/*offset=*/-1, std::move(expr), std::move(arguments));
141 }
142
Check(std::unique_ptr<SkSL::Expression> expr)143 std::unique_ptr<SkSL::Expression> DSLWriter::Check(std::unique_ptr<SkSL::Expression> expr) {
144 if (DSLWriter::Compiler().errorCount()) {
145 DSLWriter::ReportError(DSLWriter::Compiler().errorText(/*showCount=*/false).c_str());
146 DSLWriter::Compiler().setErrorCount(0);
147 }
148 return expr;
149 }
150
Coerce(std::unique_ptr<Expression> left,const SkSL::Type & type)151 DSLPossibleExpression DSLWriter::Coerce(std::unique_ptr<Expression> left, const SkSL::Type& type) {
152 return IRGenerator().coerce(std::move(left), type);
153 }
154
Construct(const SkSL::Type & type,SkTArray<DSLExpression> rawArgs)155 DSLPossibleExpression DSLWriter::Construct(const SkSL::Type& type,
156 SkTArray<DSLExpression> rawArgs) {
157 SkSL::ExpressionArray args;
158 args.reserve_back(rawArgs.size());
159
160 for (DSLExpression& arg : rawArgs) {
161 args.push_back(arg.release());
162 }
163 return SkSL::Constructor::Convert(Context(), /*offset=*/-1, type, std::move(args));
164 }
165
ConvertBinary(std::unique_ptr<Expression> left,Operator op,std::unique_ptr<Expression> right)166 std::unique_ptr<SkSL::Expression> DSLWriter::ConvertBinary(std::unique_ptr<Expression> left,
167 Operator op,
168 std::unique_ptr<Expression> right) {
169 return BinaryExpression::Convert(Context(), std::move(left), op, std::move(right));
170 }
171
ConvertField(std::unique_ptr<Expression> base,const char * name)172 std::unique_ptr<SkSL::Expression> DSLWriter::ConvertField(std::unique_ptr<Expression> base,
173 const char* name) {
174 return FieldAccess::Convert(Context(), std::move(base), name);
175 }
176
ConvertIndex(std::unique_ptr<Expression> base,std::unique_ptr<Expression> index)177 std::unique_ptr<SkSL::Expression> DSLWriter::ConvertIndex(std::unique_ptr<Expression> base,
178 std::unique_ptr<Expression> index) {
179 return IndexExpression::Convert(Context(), std::move(base), std::move(index));
180 }
181
ConvertPostfix(std::unique_ptr<Expression> expr,Operator op)182 std::unique_ptr<SkSL::Expression> DSLWriter::ConvertPostfix(std::unique_ptr<Expression> expr,
183 Operator op) {
184 return PostfixExpression::Convert(Context(), std::move(expr), op);
185 }
186
ConvertPrefix(Operator op,std::unique_ptr<Expression> expr)187 std::unique_ptr<SkSL::Expression> DSLWriter::ConvertPrefix(Operator op,
188 std::unique_ptr<Expression> expr) {
189 return PrefixExpression::Convert(Context(), op, std::move(expr));
190 }
191
ConvertSwitch(std::unique_ptr<Expression> value,ExpressionArray caseValues,SkTArray<SkSL::StatementArray> caseStatements,bool isStatic)192 DSLPossibleStatement DSLWriter::ConvertSwitch(std::unique_ptr<Expression> value,
193 ExpressionArray caseValues,
194 SkTArray<SkSL::StatementArray> caseStatements,
195 bool isStatic) {
196 StatementArray caseBlocks;
197 caseBlocks.resize(caseStatements.count());
198 for (int index = 0; index < caseStatements.count(); ++index) {
199 caseBlocks[index] = std::make_unique<SkSL::Block>(/*offset=*/-1,
200 std::move(caseStatements[index]),
201 /*symbols=*/nullptr,
202 /*isScope=*/false);
203 }
204
205 return SwitchStatement::Convert(Context(), /*offset=*/-1, isStatic, std::move(value),
206 std::move(caseValues), std::move(caseBlocks),
207 IRGenerator().fSymbolTable);
208 }
209
ReportError(const char * msg,PositionInfo * info)210 void DSLWriter::ReportError(const char* msg, PositionInfo* info) {
211 if (info && !info->file_name()) {
212 info = nullptr;
213 }
214 if (Instance().fErrorHandler) {
215 Instance().fErrorHandler->handleError(msg, info);
216 } else if (info) {
217 SK_ABORT("%s: %d: %sNo SkSL DSL error handler configured, treating this as a fatal error\n",
218 info->file_name(), info->line(), msg);
219 } else {
220 SK_ABORT("%sNo SkSL DSL error handler configured, treating this as a fatal error\n", msg);
221 }
222 }
223
Var(DSLVar & var)224 const SkSL::Variable& DSLWriter::Var(DSLVar& var) {
225 if (!var.fVar) {
226 if (var.fStorage != SkSL::VariableStorage::kParameter) {
227 DSLWriter::IRGenerator().checkVarDeclaration(/*offset=*/-1, var.fModifiers.fModifiers,
228 &var.fType.skslType(), var.fStorage);
229 }
230 std::unique_ptr<SkSL::Variable> skslvar = DSLWriter::IRGenerator().convertVar(
231 /*offset=*/-1,
232 var.fModifiers.fModifiers,
233 &var.fType.skslType(),
234 var.fName,
235 /*isArray=*/false,
236 /*arraySize=*/nullptr,
237 var.fStorage);
238 var.fVar = skslvar.get();
239 // We can't call VarDeclaration::Convert directly here, because the IRGenerator has special
240 // treatment for sk_FragColor and sk_RTHeight that we want to preserve in DSL.
241 var.fDeclaration = DSLWriter::IRGenerator().convertVarDeclaration(
242 std::move(skslvar),
243 var.fInitialValue.release());
244 }
245 return *var.fVar;
246 }
247
ParameterVar(DSLVar & var)248 std::unique_ptr<SkSL::Variable> DSLWriter::ParameterVar(DSLVar& var) {
249 // This should only be called on undeclared parameter variables, but we allow the creation to go
250 // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
251 // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
252 return DSLWriter::IRGenerator().convertVar(/*offset=*/-1, var.fModifiers.fModifiers,
253 &var.fType.skslType(), var.fName, /*isArray=*/false,
254 /*arraySize=*/nullptr, var.fStorage);
255 }
256
Declaration(DSLVar & var)257 std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVar& var) {
258 Var(var);
259 return std::move(var.fDeclaration);
260 }
261
MarkDeclared(DSLVar & var)262 void DSLWriter::MarkDeclared(DSLVar& var) {
263 SkASSERT(!var.fDeclared);
264 var.fDeclared = true;
265 }
266
ReleaseProgram()267 std::unique_ptr<SkSL::Program> DSLWriter::ReleaseProgram() {
268 DSLWriter& instance = Instance();
269 SkSL::IRGenerator& ir = IRGenerator();
270 IRGenerator::IRBundle bundle = ir.finish();
271 Pool* pool = Instance().fPool.get();
272 auto result = std::make_unique<SkSL::Program>(/*source=*/nullptr,
273 std::move(instance.fConfig),
274 Compiler().fContext,
275 std::move(bundle.fElements),
276 std::move(bundle.fSharedElements),
277 std::move(instance.fModifiersPool),
278 std::move(bundle.fSymbolTable),
279 std::move(instance.fPool),
280 bundle.fInputs);
281 if (pool) {
282 pool->detachFromThread();
283 }
284 SkASSERT(ProgramElements().empty());
285 SkASSERT(!SymbolTable());
286 return result;
287 }
288
289 #if !SK_SUPPORT_GPU || defined(SKSL_STANDALONE)
290
Instance()291 DSLWriter& DSLWriter::Instance() {
292 SkUNREACHABLE;
293 }
294
SetInstance(std::unique_ptr<DSLWriter> instance)295 void DSLWriter::SetInstance(std::unique_ptr<DSLWriter> instance) {
296 SkDEBUGFAIL("unimplemented");
297 }
298
299 #elif SKSL_USE_THREAD_LOCAL
300
301 thread_local DSLWriter* instance = nullptr;
302
Instance()303 DSLWriter& DSLWriter::Instance() {
304 SkASSERTF(instance, "dsl::Start() has not been called");
305 return *instance;
306 }
307
SetInstance(std::unique_ptr<DSLWriter> newInstance)308 void DSLWriter::SetInstance(std::unique_ptr<DSLWriter> newInstance) {
309 SkASSERT((instance == nullptr) != (newInstance == nullptr));
310 delete instance;
311 instance = newInstance.release();
312 }
313
314 #else
315
destroy_dslwriter(void * dslWriter)316 static void destroy_dslwriter(void* dslWriter) {
317 delete static_cast<DSLWriter*>(dslWriter);
318 }
319
get_pthread_key()320 static pthread_key_t get_pthread_key() {
321 static pthread_key_t sKey = []{
322 pthread_key_t key;
323 int result = pthread_key_create(&key, destroy_dslwriter);
324 if (result != 0) {
325 SK_ABORT("pthread_key_create failure: %d", result);
326 }
327 return key;
328 }();
329 return sKey;
330 }
331
Instance()332 DSLWriter& DSLWriter::Instance() {
333 DSLWriter* instance = static_cast<DSLWriter*>(pthread_getspecific(get_pthread_key()));
334 SkASSERTF(instance, "dsl::Start() has not been called");
335 return *instance;
336 }
337
SetInstance(std::unique_ptr<DSLWriter> instance)338 void DSLWriter::SetInstance(std::unique_ptr<DSLWriter> instance) {
339 delete static_cast<DSLWriter*>(pthread_getspecific(get_pthread_key()));
340 pthread_setspecific(get_pthread_key(), instance.release());
341 }
342 #endif
343
344 } // namespace dsl
345
346 } // namespace SkSL
347