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