From 08771b00ebf1cc7d3e9c0e9d4acd85066019bbde Mon Sep 17 00:00:00 2001 From: John Stiles Date: Mon, 26 Apr 2021 09:35:10 -0400 Subject: [PATCH] Add DSLVar::swap method. This gives DSLVar the ability to be set up after initial construction. To do this, we create a plain empty Var, then swap it with the actual Var we want afterwards. This allows DSL to support Vars which are `uniform half4` in some cases and `const half4` (or entirely unused) in other cases. This technique was adapted from similar code in Ethan's parser CL. Change-Id: Ic54d037a0102fda77b25d4755caf77a291eaa8c6 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/400716 Auto-Submit: John Stiles Reviewed-by: Brian Osman Commit-Queue: John Stiles --- include/sksl/DSLVar.h | 13 ++++++++++--- src/sksl/dsl/DSLVar.cpp | 13 +++++++++++++ tests/SkSLDSLTest.cpp | 15 +++++++++++++++ 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/include/sksl/DSLVar.h b/include/sksl/DSLVar.h index 3821b6886a..6a198e76aa 100644 --- a/include/sksl/DSLVar.h +++ b/include/sksl/DSLVar.h @@ -21,6 +21,11 @@ namespace dsl { class DSLVar { public: + /** + * Creates an empty, unpopulated DSLVar. Can be replaced with a real DSLVar later via `swap`. + */ + DSLVar() : fType(kVoid_Type), fDeclared(true) {} + /** * Constructs a new variable with the specified type and name. The name is used (in mangled * form) in the resulting shader code; it is not otherwise important. Since mangling prevents @@ -44,6 +49,8 @@ public: return fName; } + void swap(DSLVar& other); + DSLExpression x() { return DSLExpression(*this).x(); } @@ -125,11 +132,11 @@ private: // it to kVoid; in other words, you shouldn't generally be relying on this field to be correct. // If you need to determine the variable's type, look at DSLWriter::Var(...).type() instead. DSLType fType; - int fUniformHandle; + int fUniformHandle = -1; std::unique_ptr fDeclaration; const SkSL::Variable* fVar = nullptr; - const char* fRawName; // for error reporting - const char* fName; + const char* fRawName = nullptr; // for error reporting + const char* fName = nullptr; DSLExpression fInitialValue; VariableStorage fStorage; bool fDeclared = false; diff --git a/src/sksl/dsl/DSLVar.cpp b/src/sksl/dsl/DSLVar.cpp index cb712856f6..9918946bce 100644 --- a/src/sksl/dsl/DSLVar.cpp +++ b/src/sksl/dsl/DSLVar.cpp @@ -117,6 +117,19 @@ DSLVar::~DSLVar() { } } +void DSLVar::swap(DSLVar& other) { + std::swap(fModifiers, other.fModifiers); + std::swap(fType, other.fType); + std::swap(fUniformHandle, other.fUniformHandle); + std::swap(fDeclaration, other.fDeclaration); + std::swap(fVar, other.fVar); + std::swap(fRawName, other.fRawName); + std::swap(fName, other.fName); + std::swap(fInitialValue.fExpression, other.fInitialValue.fExpression); + std::swap(fStorage, other.fStorage); + std::swap(fDeclared, other.fDeclared); +} + DSLPossibleExpression DSLVar::operator[](DSLExpression&& index) { return DSLExpression(*this)[std::move(index)]; } diff --git a/tests/SkSLDSLTest.cpp b/tests/SkSLDSLTest.cpp index ff24efb39c..43c82e42d8 100644 --- a/tests/SkSLDSLTest.cpp +++ b/tests/SkSLDSLTest.cpp @@ -1372,6 +1372,21 @@ DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLSwizzle, r, ctxInfo) { "a.z"); } + +DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLVarSwap, r, ctxInfo) { + AutoDSLContext context(ctxInfo.directContext()->priv().getGpu(), /*markVarsDeclared=*/false); + + // We should be able to convert `a` into a proper var by swapping it, even from within a scope. + Var a; + if (true) + { + Var(kInt_Type, "a").swap(a); + } + + EXPECT_EQUAL(Statement(Block(Declare(a), a = 123)), + "{ int a; (a = 123); }"); +} + DEF_GPUTEST_FOR_MOCK_CONTEXT(DSLWhile, r, ctxInfo) { AutoDSLContext context(ctxInfo.directContext()->priv().getGpu()); Statement x = While(true, Block());