Kaido Kert | b108943 | 2024-03-18 19:46:49 -0700 | [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 | |
| 8 | #include "src/sksl/dsl/priv/DSLWriter.h" |
| 9 | |
| 10 | #include "include/sksl/DSLCore.h" |
| 11 | #include "include/sksl/DSLStatement.h" |
| 12 | #include "include/sksl/DSLSymbols.h" |
| 13 | #include "include/sksl/DSLVar.h" |
| 14 | #include "src/sksl/SkSLThreadContext.h" |
| 15 | #include "src/sksl/ir/SkSLBlock.h" |
| 16 | #include "src/sksl/ir/SkSLNop.h" |
| 17 | #include "src/sksl/ir/SkSLVarDeclarations.h" |
| 18 | #include "src/sksl/ir/SkSLVariable.h" |
| 19 | |
| 20 | namespace SkSL { |
| 21 | |
| 22 | namespace dsl { |
| 23 | |
| 24 | bool DSLWriter::ManglingEnabled() { |
| 25 | return ThreadContext::Instance().fSettings.fDSLMangling; |
| 26 | } |
| 27 | |
| 28 | std::string_view DSLWriter::Name(std::string_view name) { |
| 29 | if (ManglingEnabled()) { |
| 30 | const std::string* s = ThreadContext::SymbolTable()->takeOwnershipOfString( |
| 31 | ThreadContext::Instance().fMangler.uniqueName(name, |
| 32 | ThreadContext::SymbolTable().get())); |
| 33 | return s->c_str(); |
| 34 | } |
| 35 | return name; |
| 36 | } |
| 37 | |
| 38 | const SkSL::Variable* DSLWriter::Var(DSLVarBase& var) { |
| 39 | // fInitialized is true if we have attempted to create a var, whether or not we actually |
| 40 | // succeeded. If it's true, we don't want to try again, to avoid reporting the same error |
| 41 | // multiple times. |
| 42 | if (!var.fInitialized) { |
| 43 | // We haven't even attempted to create a var yet, so fVar ought to be null |
| 44 | SkASSERT(!var.fVar); |
| 45 | var.fInitialized = true; |
| 46 | if (var.storage() != SkSL::VariableStorage::kParameter) { |
| 47 | const SkSL::Type* baseType = &var.fType.skslType(); |
| 48 | if (baseType->isArray()) { |
| 49 | baseType = &baseType->componentType(); |
| 50 | } |
| 51 | } |
| 52 | std::unique_ptr<SkSL::Variable> skslvar = SkSL::Variable::Convert(ThreadContext::Context(), |
| 53 | var.fPosition.line(), var.fModifiers.fModifiers, &var.fType.skslType(), var.fName, |
| 54 | /*isArray=*/false, /*arraySize=*/nullptr, var.storage()); |
| 55 | SkSL::Variable* varPtr = skslvar.get(); |
| 56 | if (var.storage() != SkSL::VariableStorage::kParameter) { |
| 57 | var.fDeclaration = VarDeclaration::Convert(ThreadContext::Context(), std::move(skslvar), |
| 58 | var.fInitialValue.releaseIfPossible(), /*addToSymbolTable=*/false); |
| 59 | if (var.fDeclaration) { |
| 60 | var.fVar = varPtr; |
| 61 | var.fInitialized = true; |
| 62 | } |
| 63 | } |
| 64 | ThreadContext::ReportErrors(var.fPosition); |
| 65 | } |
| 66 | return var.fVar; |
| 67 | } |
| 68 | |
| 69 | std::unique_ptr<SkSL::Variable> DSLWriter::CreateParameterVar(DSLParameter& var) { |
| 70 | // This should only be called on undeclared parameter variables, but we allow the creation to go |
| 71 | // ahead regardless so we don't have to worry about null pointers potentially sneaking in and |
| 72 | // breaking things. DSLFunction is responsible for reporting errors for invalid parameters. |
| 73 | return SkSL::Variable::Convert(ThreadContext::Context(), var.fPosition.line(), |
| 74 | var.fModifiers.fModifiers, &var.fType.skslType(), var.fName, /*isArray=*/false, |
| 75 | /*arraySize=*/nullptr, var.storage()); |
| 76 | } |
| 77 | |
| 78 | std::unique_ptr<SkSL::Statement> DSLWriter::Declaration(DSLVarBase& var) { |
| 79 | Var(var); |
| 80 | if (!var.fDeclaration) { |
| 81 | // We should have already reported an error before ending up here, just clean up the |
| 82 | // initial value so it doesn't assert and return a nop. |
| 83 | var.fInitialValue.releaseIfPossible(); |
| 84 | return SkSL::Nop::Make(); |
| 85 | } |
| 86 | return std::move(var.fDeclaration); |
| 87 | } |
| 88 | |
| 89 | void DSLWriter::MarkDeclared(DSLVarBase& var) { |
| 90 | SkASSERT(!var.fDeclared); |
| 91 | var.fDeclared = true; |
| 92 | } |
| 93 | |
| 94 | bool DSLWriter::MarkVarsDeclared() { |
| 95 | return ThreadContext::Instance().fSettings.fDSLMarkVarsDeclared; |
| 96 | } |
| 97 | |
| 98 | void DSLWriter::AddVarDeclaration(DSLStatement& existing, DSLVar& additional) { |
| 99 | if (existing.fStatement->is<Block>()) { |
| 100 | SkSL::Block& block = existing.fStatement->as<Block>(); |
| 101 | SkASSERT(!block.isScope()); |
| 102 | block.children().push_back(Declare(additional).release()); |
| 103 | } else if (existing.fStatement->is<VarDeclaration>()) { |
| 104 | StatementArray stmts; |
| 105 | stmts.reserve_back(2); |
| 106 | stmts.push_back(std::move(existing.fStatement)); |
| 107 | stmts.push_back(Declare(additional).release()); |
| 108 | existing.fStatement = SkSL::Block::MakeUnscoped(/*line=*/-1, std::move(stmts)); |
| 109 | } else if (existing.fStatement->isEmpty()) { |
| 110 | // If the variable declaration generated an error, we can end up with a Nop statement here. |
| 111 | existing.fStatement = Declare(additional).release(); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | #if !defined(SKSL_STANDALONE) && SK_SUPPORT_GPU |
| 116 | GrGLSLUniformHandler::UniformHandle DSLWriter::VarUniformHandle(const DSLGlobalVar& var) { |
| 117 | return GrGLSLUniformHandler::UniformHandle(var.fUniformHandle); |
| 118 | } |
| 119 | #endif |
| 120 | |
| 121 | void DSLWriter::Reset() { |
| 122 | dsl::PopSymbolTable(); |
| 123 | dsl::PushSymbolTable(); |
| 124 | ThreadContext::ProgramElements().clear(); |
| 125 | ThreadContext::GetModifiersPool()->clear(); |
| 126 | } |
| 127 | |
| 128 | } // namespace dsl |
| 129 | |
| 130 | } // namespace SkSL |