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 22namespace SkSL { 23 24namespace dsl { 25 26DSLVarBase::DSLVarBase(DSLType type, skstd::string_view name, DSLExpression initialValue, 27 PositionInfo pos) 28 : DSLVarBase(DSLModifiers(), std::move(type), name, std::move(initialValue), pos) {} 29 30DSLVarBase::DSLVarBase(DSLType type, DSLExpression initialValue, PositionInfo pos) 31 : DSLVarBase(type, "var", std::move(initialValue), pos) {} 32 33DSLVarBase::DSLVarBase(const DSLModifiers& modifiers, DSLType type, DSLExpression initialValue, 34 PositionInfo pos) 35 : DSLVarBase(modifiers, type, "var", std::move(initialValue), pos) {} 36 37DSLVarBase::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 73DSLVarBase::~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 82void 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 97void DSLVar::swap(DSLVar& other) { 98 INHERITED::swap(other); 99} 100 101VariableStorage DSLVar::storage() const { 102 return VariableStorage::kLocal; 103} 104 105DSLGlobalVar::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 140void DSLGlobalVar::swap(DSLGlobalVar& other) { 141 INHERITED::swap(other); 142} 143 144VariableStorage DSLGlobalVar::storage() const { 145 return VariableStorage::kGlobal; 146} 147 148void DSLParameter::swap(DSLParameter& other) { 149 INHERITED::swap(other); 150} 151 152VariableStorage DSLParameter::storage() const { 153 return VariableStorage::kParameter; 154} 155 156 157DSLPossibleExpression DSLVarBase::operator[](DSLExpression&& index) { 158 return DSLExpression(*this, PositionInfo())[std::move(index)]; 159} 160 161DSLPossibleExpression 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 167DSLPossibleExpression DSLVar::operator=(DSLExpression expr) { 168 return this->assign(std::move(expr)); 169} 170 171DSLPossibleExpression DSLGlobalVar::operator=(DSLExpression expr) { 172 return this->assign(std::move(expr)); 173} 174 175DSLPossibleExpression DSLParameter::operator=(DSLExpression expr) { 176 return this->assign(std::move(expr)); 177} 178 179std::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 189DSLExpression 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 198DSLExpression 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 204DSLExpression 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