diff --git a/src/sksl/SkSLByteCodeGenerator.cpp b/src/sksl/SkSLByteCodeGenerator.cpp index cd4fd576e2..0ee142c176 100644 --- a/src/sksl/SkSLByteCodeGenerator.cpp +++ b/src/sksl/SkSLByteCodeGenerator.cpp @@ -1557,15 +1557,24 @@ public: // 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().fComponents[component]; + expr = expr->as().fBase.get(); + } while (expr->is()); + + 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 04ee1b3f3c..31b0bea2ed 100644 --- a/tests/SkSLInterpreterTest.cpp +++ b/tests/SkSLInterpreterTest.cpp @@ -815,6 +815,20 @@ DEF_TEST(SkSLInterpreterOutParams, r) { 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];