• 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/sksl/DSLCore.h"
11 #include "include/sksl/DSLStatement.h"
12 #include "include/sksl/DSLSymbols.h"
13 #include "include/sksl/DSLVar.h"
14 #include "src/sksl/SkSLThreadContext.h"
15 #include "src/sksl/ir/SkSLBlock.h"
16 #include "src/sksl/ir/SkSLNop.h"
17 #include "src/sksl/ir/SkSLVarDeclarations.h"
18 #include "src/sksl/ir/SkSLVariable.h"
19 
20 namespace SkSL {
21 
22 namespace dsl {
23 
ManglingEnabled()24 bool DSLWriter::ManglingEnabled() {
25     return ThreadContext::Instance().fSettings.fDSLMangling;
26 }
27 
Name(skstd::string_view name)28 skstd::string_view DSLWriter::Name(skstd::string_view name) {
29     if (ManglingEnabled()) {
30         const String* s = ThreadContext::SymbolTable()->takeOwnershipOfString(
31                 ThreadContext::Instance().fMangler.uniqueName(name,
32                     ThreadContext::SymbolTable().get()));
33         return s->c_str();
34     }
35     return name;
36 }
37 
Var(DSLVarBase & var)38 const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) {
39     // fInitialized is true if we have attempted to create a var, whether or not we actually
40     // succeeded. If it's true, we don't want to try again, to avoid reporting the same error
41     // multiple times.
42     if (!var.fInitialized) {
43         // We haven't even attempted to create a var yet, so fVar ought to be null
44         SkASSERT(!var.fVar);
45         var.fInitialized = true;
46         if (var.storage() != SkSL::VariableStorage::kParameter) {
47             const SkSL::Type* baseType = &var.fType.skslType();
48             if (baseType->isArray()) {
49                 baseType = &baseType->componentType();
50             }
51         }
52         std::unique_ptr<SkSL::Variable> skslvar = SkSL::Variable::Convert(ThreadContext::Context(),
53                 var.fPosition.line(), var.fModifiers.fModifiers, &var.fType.skslType(), var.fName,
54                 /*isArray=*/false, /*arraySize=*/nullptr, var.storage());
55         SkSL::Variable* varPtr = skslvar.get();
56         if (var.storage() != SkSL::VariableStorage::kParameter) {
57             var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(), std::move(skslvar),
58                     var.fInitialValue.releaseIfPossible(), /*addToSymbolTable=*/false);
59             if (var.fDeclaration) {
60                 var.fVar = varPtr;
61                 var.fInitialized = true;
62             }
63         }
64         ThreadContext::ReportErrors(var.fPosition);
65     }
66     return var.fVar;
67 }
68 
CreateParameterVar(DSLParameter & var)69 std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) {
70     // This should only be called on undeclared parameter variables, but we allow the creation to go
71     // ahead regardless so we don't have to worry about null pointers potentially sneaking in and
72     // breaking things. DSLFunction is responsible for reporting errors for invalid parameters.
73     return SkSL::Variable::Convert(ThreadContext::Context(), var.fPosition.line(),
74             var.fModifiers.fModifiers, &var.fType.skslType(), var.fName, /*isArray=*/false,
75             /*arraySize=*/nullptr, var.storage());
76 }
77 
Declaration(DSLVarBase & var)78 std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) {
79     Var(var);
80     if (!var.fDeclaration) {
81         // We should have already reported an error before ending up here, just clean up the
82         // initial value so it doesn't assert and return a nop.
83         var.fInitialValue.releaseIfPossible();
84         return SkSL::Nop::Make();
85     }
86     return std::move(var.fDeclaration);
87 }
88 
MarkDeclared(DSLVarBase & var)89 void DSLWriter::MarkDeclared(DSLVarBase& var) {
90     SkASSERT(!var.fDeclared);
91     var.fDeclared = true;
92 }
93 
MarkVarsDeclared()94 bool DSLWriter::MarkVarsDeclared() {
95     return ThreadContext::Instance().fSettings.fDSLMarkVarsDeclared;
96 }
97 
AddVarDeclaration(DSLStatement & existing,DSLVar & additional)98 void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) {
99     if (existing.fStatement->is<Block>()) {
100         SkSL::Block& block = existing.fStatement->as<Block>();
101         SkASSERT(!block.isScope());
102         block.children().push_back(Declare(additional).release());
103     } else if (existing.fStatement->is<VarDeclaration>()) {
104         StatementArray stmts;
105         stmts.reserve_back(2);
106         stmts.push_back(std::move(existing.fStatement));
107         stmts.push_back(Declare(additional).release());
108         existing.fStatement = SkSL::Block::MakeUnscoped(/*line=*/-1, std::move(stmts));
109     } else if (existing.fStatement->isEmpty()) {
110         // If the variable declaration generated an error, we can end up with a Nop statement here.
111         existing.fStatement = Declare(additional).release();
112     }
113 }
114 
115 #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU
VarUniformHandle(const DSLGlobalVar & var)116 GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) {
117     return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle);
118 }
119 #endif
120 
Reset()121 void DSLWriter::Reset() {
122     dsl::PopSymbolTable();
123     dsl::PushSymbolTable();
124     ThreadContext::ProgramElements().clear();
125     ThreadContext::GetModifiersPool()->clear();
126 }
127 
128 } // namespace dsl
129 
130 } // namespace SkSL
131