• 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 "include/sksl/DSLVar.h"
9 
10 #include "include/sksl/DSLModifiers.h"
11 #include "include/sksl/DSLType.h"
12 #include "src/sksl/SkSLCompiler.h"
13 #include "src/sksl/SkSLThreadContext.h"
14 #include "src/sksl/SkSLUtil.h"
15 #include "src/sksl/dsl/priv/DSLWriter.h"
16 #include "src/sksl/ir/SkSLBinaryExpression.h"
17 #include "src/sksl/ir/SkSLFunctionCall.h"
18 #include "src/sksl/ir/SkSLSymbolTable.h"
19 #include "src/sksl/ir/SkSLVariable.h"
20 #include "src/sksl/ir/SkSLVariableReference.h"
21 
22 namespace SkSL {
23 
24 namespace dsl {
25 
DSLVarBase(DSLType type,skstd::string_view name,DSLExpression initialValue,PositionInfo pos)26 DSLVarBase::DSLVarBase(DSLType type, skstd::string_view name, DSLExpression initialValue,
27                        PositionInfo pos)
28     : DSLVarBase(DSLModifiers(), std::move(type), name, std::move(initialValue), pos) {}
29 
DSLVarBase(DSLType type,DSLExpression initialValue,PositionInfo pos)30 DSLVarBase::DSLVarBase(DSLType type, DSLExpression initialValue, PositionInfo pos)
31     : DSLVarBase(type, "var", std::move(initialValue), pos) {}
32 
DSLVarBase(const DSLModifiers & modifiers,DSLType type,DSLExpression initialValue,PositionInfo pos)33 DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, DSLExpression initialValue,
34                        PositionInfo pos)
35     : DSLVarBase(modifiers, type, "var", std::move(initialValue), pos) {}
36 
DSLVarBase(const DSLModifiers & modifiers,DSLType type,skstd::string_view name,DSLExpression initialValue,PositionInfo pos)37 DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, skstd::string_view name,
38                        DSLExpression initialValue, PositionInfo pos)
39     : fModifiers(std::move(modifiers))
40     , fType(std::move(type))
41     , fRawName(name)
42     , fName(fType.skslType().isOpaque() ? name : DSLWriter::Name(name))
43     , fInitialValue(std::move(initialValue))
44     , fDeclared(DSLWriter::MarkVarsDeclared())
45     , fPosition(pos) {
46     if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
47 #if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
48         if (ThreadContext::InFragmentProcessor()) {
49             const SkSL::Type& skslType = type.skslType();
50             GrSLType grslType;
51             int count;
52             if (skslType.isArray()) {
53                 SkAssertResult(SkSL::type_to_grsltype(ThreadContext::Context(),
54                         skslType.componentType(), &grslType));
55                 count = skslType.columns();
56                 SkASSERT(count > 0);
57             } else {
58                 SkAssertResult(SkSL::type_to_grsltype(ThreadContext::Context(), skslType,
59                         &grslType));
60                 count = 0;
61             }
62             const char* uniformName;
63             SkASSERT(ThreadContext::CurrentEmitArgs());
64             fUniformHandle = ThreadContext::CurrentEmitArgs()->fUniformHandler->addUniformArray(
65                     &ThreadContext::CurrentEmitArgs()->fFp, kFragment_GrShaderFlag, grslType,
66                     String(this->name()).c_str(), count, &uniformName).toIndex();
67             fName = uniformName;
68         }
69 #endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
70     }
71 }
72 
~DSLVarBase()73 DSLVarBase::~DSLVarBase() {
74     if (fDeclaration && !fDeclared) {
75         ThreadContext::ReportError(String::printf("variable '%.*s' was destroyed without being "
76                                                   "declared",
77                                                   (int)fRawName.length(),
78                                                   fRawName.data()).c_str());
79     }
80 }
81 
swap(DSLVarBase & other)82 void DSLVarBase::swap(DSLVarBase& other) {
83     SkASSERT(this->storage() == other.storage());
84     std::swap(fModifiers, other.fModifiers);
85     std::swap(fType, other.fType);
86     std::swap(fUniformHandle, other.fUniformHandle);
87     std::swap(fDeclaration, other.fDeclaration);
88     std::swap(fVar, other.fVar);
89     std::swap(fRawName, other.fRawName);
90     std::swap(fName, other.fName);
91     std::swap(fInitialValue.fExpression, other.fInitialValue.fExpression);
92     std::swap(fDeclared, other.fDeclared);
93     std::swap(fInitialized, other.fInitialized);
94     std::swap(fPosition, other.fPosition);
95 }
96 
swap(DSLVar & other)97 void DSLVar::swap(DSLVar& other) {
98     INHERITED::swap(other);
99 }
100 
storage() const101 VariableStorage DSLVar::storage() const {
102     return VariableStorage::kLocal;
103 }
104 
DSLGlobalVar(const char * name)105 DSLGlobalVar::DSLGlobalVar(const char* name)
106     : INHERITED(kVoid_Type, name, DSLExpression(), PositionInfo()) {
107     fName = name;
108     DSLWriter::MarkDeclared(*this);
109 #if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
110     if (!strcmp(name, "sk_SampleCoord")) {
111         fName = ThreadContext::CurrentEmitArgs()->fSampleCoord;
112         // The actual sk_SampleCoord variable hasn't been created by GrGLSLFPFragmentBuilder yet, so
113         // if we attempt to look it up in the symbol table we'll get null. As we are currently
114         // converting all DSL code into strings rather than nodes, all we really need is a
115         // correctly-named variable with the right type, so we just create a placeholder for it.
116         // TODO(skia/11330): we'll need to fix this when switching over to nodes.
117         const SkSL::Modifiers* modifiers = ThreadContext::Context().fModifiersPool->add(
118                 SkSL::Modifiers(SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
119                                              /*binding=*/-1, /*index=*/-1, /*set=*/-1,
120                                              SK_MAIN_COORDS_BUILTIN, /*inputAttachmentIndex=*/-1),
121                                 SkSL::Modifiers::kNo_Flag));
122 
123         fVar = ThreadContext::SymbolTable()->takeOwnershipOfIRNode(std::make_unique<SkSL::Variable>(
124                 /*line=*/-1,
125                 modifiers,
126                 fName,
127                 ThreadContext::Context().fTypes.fFloat2.get(),
128                 /*builtin=*/true,
129                 SkSL::VariableStorage::kGlobal));
130         fInitialized = true;
131         return;
132     }
133 #endif
134     const SkSL::Symbol* result = (*ThreadContext::SymbolTable())[fName];
135     SkASSERTF(result, "could not find '%.*s' in symbol table", (int)fName.length(), fName.data());
136     fVar = &result->as<SkSL::Variable>();
137     fInitialized = true;
138 }
139 
swap(DSLGlobalVar & other)140 void DSLGlobalVar::swap(DSLGlobalVar& other) {
141     INHERITED::swap(other);
142 }
143 
storage() const144 VariableStorage DSLGlobalVar::storage() const {
145     return VariableStorage::kGlobal;
146 }
147 
swap(DSLParameter & other)148 void DSLParameter::swap(DSLParameter& other) {
149     INHERITED::swap(other);
150 }
151 
storage() const152 VariableStorage DSLParameter::storage() const {
153     return VariableStorage::kParameter;
154 }
155 
156 
operator [](DSLExpression && index)157 DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) {
158     return DSLExpression(*this, PositionInfo())[std::move(index)];
159 }
160 
assign(DSLExpression expr)161 DSLPossibleExpression DSLVarBase::assign(DSLExpression expr) {
162     return BinaryExpression::Convert(ThreadContext::Context(),
163             DSLExpression(*this, PositionInfo()).release(), SkSL::Token::Kind::TK_EQ,
164             expr.release());
165 }
166 
operator =(DSLExpression expr)167 DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
168     return this->assign(std::move(expr));
169 }
170 
operator =(DSLExpression expr)171 DSLPossibleExpression DSLGlobalVar::operator=(DSLExpression expr) {
172     return this->assign(std::move(expr));
173 }
174 
operator =(DSLExpression expr)175 DSLPossibleExpression DSLParameter::operator=(DSLExpression expr) {
176     return this->assign(std::move(expr));
177 }
178 
methodCall(skstd::string_view methodName,PositionInfo pos)179 std::unique_ptr<SkSL::Expression> DSLGlobalVar::methodCall(skstd::string_view methodName,
180                                                            PositionInfo pos) {
181     if (!this->fType.isEffectChild()) {
182         ThreadContext::ReportError("type does not support method calls", pos);
183         return nullptr;
184     }
185     return FieldAccess::Convert(ThreadContext::Context(), *ThreadContext::SymbolTable(),
186             DSLExpression(*this, PositionInfo()).release(), methodName);
187 }
188 
eval(ExpressionArray args,PositionInfo pos)189 DSLExpression DSLGlobalVar::eval(ExpressionArray args, PositionInfo pos) {
190     auto method = this->methodCall("eval", pos);
191     return DSLExpression(
192             method ? SkSL::FunctionCall::Convert(ThreadContext::Context(), pos.line(),
193                                                  std::move(method), std::move(args))
194                    : nullptr,
195             pos);
196 }
197 
eval(DSLExpression x,PositionInfo pos)198 DSLExpression DSLGlobalVar::eval(DSLExpression x, PositionInfo pos) {
199     ExpressionArray converted;
200     converted.push_back(x.release());
201     return this->eval(std::move(converted), pos);
202 }
203 
eval(DSLExpression x,DSLExpression y,PositionInfo pos)204 DSLExpression DSLGlobalVar::eval(DSLExpression x, DSLExpression y, PositionInfo pos) {
205     ExpressionArray converted;
206     converted.push_back(x.release());
207     converted.push_back(y.release());
208     return this->eval(std::move(converted), pos);
209 }
210 
211 } // namespace dsl
212 
213 } // namespace SkSL
214