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