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/SkSLUtil.h"
14 #include "src/sksl/dsl/priv/DSLWriter.h"
15 #include "src/sksl/ir/SkSLBinaryExpression.h"
16 #include "src/sksl/ir/SkSLSymbolTable.h"
17 #include "src/sksl/ir/SkSLVariable.h"
18 #include "src/sksl/ir/SkSLVariableReference.h"
19 
20 namespace SkSL {
21 
22 namespace dsl {
23 
DSLVar(const char * name)24 DSLVar::DSLVar(const char* name)
25     : fType(kVoid_Type)
26     , fRawName(name)
27     , fName(name)
28     , fDeclared(true) {
29 #if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
30     if (!strcmp(name, "sk_SampleCoord")) {
31         fName = DSLWriter::CurrentEmitArgs()->fSampleCoord;
32         // The actual sk_SampleCoord variable hasn't been created by GrGLSLFPFragmentBuilder yet, so
33         // if we attempt to look it up in the symbol table we'll get null. As we are currently
34         // converting all DSL code into strings rather than nodes, all we really need is a
35         // correctly-named variable with the right type, so we just create a placeholder for it.
36         // TODO(skia/11330): we'll need to fix this when switching over to nodes.
37         const SkSL::Modifiers* modifiers = DSLWriter::Context().fModifiersPool->add(
38                 SkSL::Modifiers(SkSL::Layout(/*flags=*/0, /*location=*/-1, /*offset=*/-1,
39                                              /*binding=*/-1, /*index=*/-1, /*set=*/-1,
40                                              SK_MAIN_COORDS_BUILTIN, /*inputAttachmentIndex=*/-1,
41                                              Layout::kUnspecified_Primitive, /*maxVertices=*/1,
42                                              /*invocations=*/-1, /*when=*/"",
43                                              Layout::CType::kDefault),
44                                 SkSL::Modifiers::kNo_Flag));
45 
46         fVar = DSLWriter::SymbolTable()->takeOwnershipOfIRNode(std::make_unique<SkSL::Variable>(
47                 /*offset=*/-1,
48                 modifiers,
49                 fName,
50                 DSLWriter::Context().fTypes.fFloat2.get(),
51                 /*builtin=*/true,
52                 SkSL::VariableStorage::kGlobal));
53         return;
54     }
55 #endif
56     const SkSL::Symbol* result = (*DSLWriter::SymbolTable())[fName];
57     SkASSERTF(result, "could not find '%s' in symbol table", fName);
58     fVar = &result->as<SkSL::Variable>();
59 }
60 
DSLVar(DSLType type,const char * name,DSLExpression initialValue)61 DSLVar::DSLVar(DSLType type, const char* name, DSLExpression initialValue)
62     : DSLVar(DSLModifiers(), std::move(type), name, std::move(initialValue)) {}
63 
DSLVar(DSLType type,DSLExpression initialValue)64 DSLVar::DSLVar(DSLType type, DSLExpression initialValue)
65     : DSLVar(type, "var", std::move(initialValue)) {}
66 
DSLVar(DSLModifiers modifiers,DSLType type,DSLExpression initialValue)67 DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, DSLExpression initialValue)
68     : DSLVar(modifiers, type, "var", std::move(initialValue)) {}
69 
DSLVar(DSLModifiers modifiers,DSLType type,const char * name,DSLExpression initialValue)70 DSLVar::DSLVar(DSLModifiers modifiers, DSLType type, const char* name, DSLExpression initialValue)
71     : fModifiers(std::move(modifiers))
72     , fType(std::move(type))
73     , fRawName(name)
74     , fName(fType.skslType().isOpaque() ? name : DSLWriter::Name(name))
75     , fInitialValue(std::move(initialValue))
76     , fStorage(Variable::Storage::kLocal)
77     , fDeclared(DSLWriter::Instance().fMarkVarsDeclared) {
78 #if SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
79     if (fModifiers.fModifiers.fFlags & Modifiers::kUniform_Flag) {
80         fStorage = Variable::Storage::kGlobal;
81         if (DSLWriter::InFragmentProcessor()) {
82             const SkSL::Type& skslType = type.skslType();
83             GrSLType grslType;
84             int count;
85             if (skslType.isArray()) {
86                 SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(),
87                                                       skslType.componentType(),
88                                                       &grslType));
89                 count = skslType.columns();
90                 SkASSERT(count > 0);
91             } else {
92                 SkAssertResult(SkSL::type_to_grsltype(DSLWriter::Context(), skslType,
93                                                       &grslType));
94                 count = 0;
95             }
96             const char* name;
97             SkASSERT(DSLWriter::CurrentEmitArgs());
98             fUniformHandle = DSLWriter::CurrentEmitArgs()->fUniformHandler->addUniformArray(
99                                                                  &DSLWriter::CurrentEmitArgs()->fFp,
100                                                                  kFragment_GrShaderFlag,
101                                                                  grslType,
102                                                                  this->name(),
103                                                                  count,
104                                                                  &name).toIndex();
105             fName = name;
106         }
107     }
108 #endif // SK_SUPPORT_GPU && !defined(SKSL_STANDALONE)
109 }
110 
~DSLVar()111 DSLVar::~DSLVar() {
112     if (!fDeclared) {
113         DSLWriter::ReportError(String::printf("error: variable '%s' was destroyed without being "
114                                               "declared\n", fRawName).c_str());
115     }
116 }
117 
swap(DSLVar & other)118 void DSLVar::swap(DSLVar& other) {
119     std::swap(fModifiers, other.fModifiers);
120     std::swap(fType, other.fType);
121     std::swap(fUniformHandle, other.fUniformHandle);
122     std::swap(fDeclaration, other.fDeclaration);
123     std::swap(fVar, other.fVar);
124     std::swap(fRawName, other.fRawName);
125     std::swap(fName, other.fName);
126     std::swap(fInitialValue.fExpression, other.fInitialValue.fExpression);
127     std::swap(fStorage, other.fStorage);
128     std::swap(fDeclared, other.fDeclared);
129 }
130 
operator [](DSLExpression && index)131 DSLPossibleExpression DSLVar::operator[](DSLExpression&& index) {
132     return DSLExpression(*this)[std::move(index)];
133 }
134 
operator =(DSLExpression expr)135 DSLPossibleExpression DSLVar::operator=(DSLExpression expr) {
136     return DSLWriter::ConvertBinary(DSLExpression(*this).release(), SkSL::Token::Kind::TK_EQ,
137                                     expr.release());
138 }
139 
140 } // namespace dsl
141 
142 } // namespace SkSL
143