• 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 #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