Fix swizzle-of-swizzle lvalues in ByteCodeGenerator
Bug: skia:10785
Change-Id: I01708af63d7e2ffc160022074ea9ff2b3c69eab5
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/320638
Reviewed-by: John Stiles <johnstiles@google.com>
Commit-Queue: Brian Osman <brianosman@google.com>
diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp
index cd4fd57..0ee142c 100644
--- a/src/sksl/SkSLByteCodeGenerator.cpp
+++ b/src/sksl/SkSLByteCodeGenerator.cpp
@@ -1557,15 +1557,24 @@
// because the stack doesn't let us retain that address between stores. Dynamic locations
// are rare though, and swizzled writes to those are even rarer, so we just live with this.
for (int i = count; i-- > 0;) {
- ByteCodeGenerator::Location location = fGenerator.getLocation(*fSwizzle.fBase);
+ // If we have a swizzle-of-swizzle lvalue, we need to flatten that down to the final
+ // component index. (getLocation can't handle this case).
+ const Expression* expr = &fSwizzle;
+ int component = i;
+ do {
+ component = expr->as<Swizzle>().fComponents[component];
+ expr = expr->as<Swizzle>().fBase.get();
+ } while (expr->is<Swizzle>());
+
+ ByteCodeGenerator::Location location = fGenerator.getLocation(*expr);
if (!location.isOnStack()) {
fGenerator.write(location.selectStore(ByteCodeInstruction::kStore,
ByteCodeInstruction::kStoreGlobal),
1);
- fGenerator.write8(location.fSlot + fSwizzle.fComponents[i]);
+ fGenerator.write8(location.fSlot + component);
} else {
fGenerator.write(ByteCodeInstruction::kPushImmediate);
- fGenerator.write32(fSwizzle.fComponents[i]);
+ fGenerator.write32(component);
fGenerator.write(ByteCodeInstruction::kAddI, 1);
fGenerator.write(location.selectStore(ByteCodeInstruction::kStoreExtended,
ByteCodeInstruction::kStoreExtendedGlobal),
diff --git a/tests/SkSLInterpreterTest.cpp b/tests/SkSLInterpreterTest.cpp
index 04ee1b3..31b0bea 100644
--- a/tests/SkSLInterpreterTest.cpp
+++ b/tests/SkSLInterpreterTest.cpp
@@ -815,6 +815,20 @@
1, 2, 3, 4, 3, 3, 1, 5);
}
+DEF_TEST(SkSLInterpreterSwizzleSingleLvalue, r) {
+ // Add in your SkSL here.
+ test(r,
+ "void main(inout half4 color) { color.xywz = half4(1,2,3,4); }",
+ 0, 0, 0, 0, 1, 2, 4, 3);
+}
+
+DEF_TEST(SkSLInterpreterSwizzleDoubleLvalue, r) {
+ // Add in your SkSL here.
+ test(r,
+ "void main(inout half4 color) { color.xywz.yxzw = half4(1,2,3,4); }",
+ 0, 0, 0, 0, 2, 1, 4, 3);
+}
+
DEF_TEST(SkSLInterpreterMathFunctions, r) {
float value[4], expected[4];