Add WGSL support for comma-expressions.
We can now use `assembleExpression` to cause side effects from the
left-hand side to occur, and then just discard the result.
Change-Id: I9e52110879e0916f7f9dce1257c62e04603aa3c1
Bug: skia:13092
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/706976
Auto-Submit: John Stiles <johnstiles@google.com>
Reviewed-by: Arman Uguray <armansito@google.com>
Commit-Queue: Arman Uguray <armansito@google.com>
diff --git a/gn/sksl_tests.gni b/gn/sksl_tests.gni
index 8a51c77..ec324e7 100644
--- a/gn/sksl_tests.gni
+++ b/gn/sksl_tests.gni
@@ -404,6 +404,8 @@
"shared/ArrayFollowedByScalar.sksl",
"shared/ArrayIndexTypes.sksl",
"shared/ArrayTypes.sksl",
+ "shared/CommaMixedTypes.sksl",
+ "shared/CommaSideEffects.sksl",
"shared/ConstArray.sksl",
"shared/ConstantIf.sksl",
"shared/FunctionAnonymousParameters.sksl",
@@ -414,6 +416,7 @@
"shared/IntegerDivisionES3.sksl",
"shared/LogicalAndShortCircuit.sksl",
"shared/LogicalOrShortCircuit.sksl",
+ "shared/Matrices.sksl",
"shared/MatrixConstructorsES2.sksl",
"shared/MatrixConstructorsES3.sksl",
"shared/MatrixEquality.sksl",
@@ -452,7 +455,6 @@
"wgsl/MainDoesNotHaveFragCoordParameter.sksl",
"wgsl/MainHasFragCoordParameter.sksl",
"wgsl/MainHasVoidReturn.sksl",
- "wgsl/Matrices.sksl",
"wgsl/MatrixConstructorDiagonal.sksl",
"wgsl/OutParams.sksl",
"wgsl/TernaryThenShortCircuit.sksl",
diff --git a/resources/sksl/BUILD.bazel b/resources/sksl/BUILD.bazel
index fcc6177..ff45544 100644
--- a/resources/sksl/BUILD.bazel
+++ b/resources/sksl/BUILD.bazel
@@ -1064,7 +1064,6 @@
"wgsl/MainDoesNotHaveFragCoordParameter.sksl",
"wgsl/MainHasFragCoordParameter.sksl",
"wgsl/MainHasVoidReturn.sksl",
- "wgsl/Matrices.sksl",
"wgsl/MatrixConstructorDiagonal.sksl",
"wgsl/OutParams.sksl",
"wgsl/TernaryThenShortCircuit.sksl",
@@ -1082,6 +1081,8 @@
"shared/ArrayFollowedByScalar.sksl",
"shared/ArrayIndexTypes.sksl",
"shared/ArrayTypes.sksl",
+ "shared/CommaMixedTypes.sksl",
+ "shared/CommaSideEffects.sksl",
"shared/ConstArray.sksl",
"shared/ConstantIf.sksl",
"shared/FunctionAnonymousParameters.sksl",
@@ -1092,6 +1093,7 @@
"shared/IntegerDivisionES3.sksl",
"shared/LogicalAndShortCircuit.sksl",
"shared/LogicalOrShortCircuit.sksl",
+ "shared/Matrices.sksl",
"shared/MatrixConstructorsES2.sksl",
"shared/MatrixConstructorsES3.sksl",
"shared/MatrixEquality.sksl",
diff --git a/resources/sksl/wgsl/Matrices.sksl b/resources/sksl/wgsl/Matrices.sksl
deleted file mode 100644
index edfefc2..0000000
--- a/resources/sksl/wgsl/Matrices.sksl
+++ /dev/null
@@ -1,90 +0,0 @@
-// TODO(skia:13902): Remove this test in favor of shared/Matrices.sksl when WGSL codegen can handle
-// the comma-separated statement syntax (exercised by the `test_comma()` function in that file).
-
-uniform half4 colorGreen, colorRed;
-
-bool test_float() {
- bool ok = true;
-
- float2x2 m1 = float2x2(float4(1, 2, 3, 4));
- ok = ok && (m1 == float2x2(1, 2, 3, 4));
-
- // This generates {5, 0, 0, 5} on some Radeon GPUs.
-// float2x2 m2 = float2x2(float4(5));
-// ok = ok && (m2 == float2x2(5, 5, 5, 5));
-
- float2x2 m3 = float2x2(m1);
- ok = ok && (m3 == float2x2(1, 2, 3, 4));
-
- float2x2 m4 = float2x2(6);
- ok = ok && (m4 == float2x2(6, 0, 0, 6));
-
- m3 *= m4;
- ok = ok && (m3 == float2x2(6, 12, 18, 24));
-
- float2x2 m5 = float2x2(m1[1][1]);
- ok = ok && (m5 == float2x2(4, 0, 0, 4));
-
- m1 += m5;
- ok = ok && (m1 == float2x2(5, 2, 3, 8));
-
- float2x2 m7 = float2x2(5, float3(6, 7, 8));
- ok = ok && (m7 == float2x2(5, 6, 7, 8));
-
- float3x3 m9 = float3x3(9);
- ok = ok && (m9 == float3x3(9, 0, 0, 0, 9, 0, 0, 0, 9));
-
- float4x4 m10 = float4x4(11);
- ok = ok && (m10 == float4x4(11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11));
-
- float4x4 m11 = float4x4(20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20);
- m11 -= m10;
- ok = ok && (m11 == float4x4(9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9));
-
- return ok;
-}
-
-bool test_half() {
- bool ok = true;
-
- half2x2 m1 = half2x2(half4(1, 2, 3, 4));
- ok = ok && (m1 == half2x2(1, 2, 3, 4));
-
- // This generates {5, 0, 0, 5} on some Radeon GPUs.
-// half2x2 m2 = half2x2(half4(5));
-// ok = ok && (m2 == half2x2(5, 5, 5, 5));
-
- half2x2 m3 = half2x2(m1);
- ok = ok && (m3 == half2x2(1, 2, 3, 4));
-
- half2x2 m4 = half2x2(6);
- ok = ok && (m4 == half2x2(6, 0, 0, 6));
-
- m3 *= m4;
- ok = ok && (m3 == half2x2(6, 12, 18, 24));
-
- half2x2 m5 = half2x2(m1[1][1]);
- ok = ok && (m5 == half2x2(4, 0, 0, 4));
-
- m1 += m5;
- ok = ok && (m1 == half2x2(5, 2, 3, 8));
-
- half2x2 m7 = half2x2(5, half3(6, 7, 8));
- ok = ok && (m7 == half2x2(5, 6, 7, 8));
-
- half3x3 m9 = half3x3(9);
- ok = ok && (m9 == half3x3(9, 0, 0, 0, 9, 0, 0, 0, 9));
-
- half4x4 m10 = half4x4(11);
- ok = ok && (m10 == half4x4(11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11, 0, 0, 0, 0, 11));
-
- half4x4 m11 = half4x4(20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20);
- m11 -= m10;
- ok = ok && (m11 == half4x4(9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9, 20, 20, 20, 20, 9));
-
- return ok;
-}
-
-half4 main(float2 coords) {
- return test_float() && test_half() ? colorGreen : colorRed;
-}
diff --git a/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp b/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
index 043d487..7cb468c 100644
--- a/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
+++ b/src/sksl/codegen/SkSLWGSLCodeGenerator.cpp
@@ -1177,6 +1177,15 @@
return expr;
}
+ // Handle comma-expressions.
+ if (op.kind() == OperatorKind::COMMA) {
+ // The result from the left-expression is ignored, but its side effects must occur.
+ this->assembleExpression(left, Precedence::kStatement);
+
+ // Evaluate the right side normally.
+ return this->assembleExpression(right, parentPrecedence);
+ }
+
// Handle assignment-expressions.
if (op.isAssignment()) {
std::unique_ptr<LValue> lvalue = this->makeLValue(left);
diff --git a/tests/sksl/shared/CommaMixedTypes.wgsl b/tests/sksl/shared/CommaMixedTypes.wgsl
new file mode 100644
index 0000000..ae2a6e7
--- /dev/null
+++ b/tests/sksl/shared/CommaMixedTypes.wgsl
@@ -0,0 +1,28 @@
+struct FSIn {
+ @builtin(front_facing) sk_Clockwise: bool,
+ @builtin(position) sk_FragCoord: vec4<f32>,
+};
+struct FSOut {
+ @location(0) sk_FragColor: vec4<f32>,
+};
+struct _GlobalUniforms {
+ colorGreen: vec4<f32>,
+ unknownInput: f32,
+};
+@binding(0) @group(0) var<uniform> _globalUniforms: _GlobalUniforms;
+fn mat2x2f32_diagonal(x: f32) -> mat2x2<f32> {
+ return mat2x2<f32>(x, 0.0, 0.0, x);
+}
+fn main(coords: vec2<f32>) -> vec4<f32> {
+ var result: vec4<f32>;
+ result.x = _globalUniforms.colorGreen.x;
+ result.y = _globalUniforms.colorGreen.y;
+ result.z = _globalUniforms.colorGreen.z;
+ result.w = _globalUniforms.colorGreen.w;
+ return result;
+}
+@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
+ var _stageOut: FSOut;
+ _stageOut.sk_FragColor = main(_stageIn.sk_FragCoord.xy);
+ return _stageOut;
+}
diff --git a/tests/sksl/shared/CommaSideEffects.wgsl b/tests/sksl/shared/CommaSideEffects.wgsl
new file mode 100644
index 0000000..4f0dec1
--- /dev/null
+++ b/tests/sksl/shared/CommaSideEffects.wgsl
@@ -0,0 +1,42 @@
+struct FSIn {
+ @builtin(front_facing) sk_Clockwise: bool,
+ @builtin(position) sk_FragCoord: vec4<f32>,
+};
+struct FSOut {
+ @location(0) sk_FragColor: vec4<f32>,
+};
+struct _GlobalUniforms {
+ colorRed: vec4<f32>,
+ colorGreen: vec4<f32>,
+ colorWhite: vec4<f32>,
+ colorBlack: vec4<f32>,
+};
+@binding(0) @group(0) var<uniform> _globalUniforms: _GlobalUniforms;
+fn _outParamHelper_0_setToColorBlack_vh4(d: ptr<function, vec4<f32>>) {
+ var _var0: vec4<f32>;
+ setToColorBlack_vh4(&_var0);
+ (*d) = _var0;
+}
+fn setToColorBlack_vh4(x: ptr<function, vec4<f32>>) {
+ (*x) = _globalUniforms.colorBlack;
+}
+fn main(coords: vec2<f32>) -> vec4<f32> {
+ var a: vec4<f32>;
+ var b: vec4<f32>;
+ var c: vec4<f32>;
+ var d: vec4<f32>;
+ b = _globalUniforms.colorRed;
+ c = _globalUniforms.colorGreen;
+ _outParamHelper_0_setToColorBlack_vh4(&d);
+ a = _globalUniforms.colorWhite;
+ a = a * a;
+ b = b * b;
+ c = c * c;
+ d = d * d;
+ return select(_globalUniforms.colorRed, _globalUniforms.colorGreen, vec4<bool>(((all(a == _globalUniforms.colorWhite) && all(b == _globalUniforms.colorRed)) && all(c == _globalUniforms.colorGreen)) && all(d == _globalUniforms.colorBlack)));
+}
+@fragment fn fragmentMain(_stageIn: FSIn) -> FSOut {
+ var _stageOut: FSOut;
+ _stageOut.sk_FragColor = main(_stageIn.sk_FragCoord.xy);
+ return _stageOut;
+}
diff --git a/tests/sksl/wgsl/Matrices.wgsl b/tests/sksl/shared/Matrices.wgsl
similarity index 91%
rename from tests/sksl/wgsl/Matrices.wgsl
rename to tests/sksl/shared/Matrices.wgsl
index 5df1caf..25a3b1a 100644
--- a/tests/sksl/wgsl/Matrices.wgsl
+++ b/tests/sksl/shared/Matrices.wgsl
@@ -59,6 +59,13 @@
ok = ok && mat4x4f32_eq_mat4x4f32(m11, mat4x4<f32>(vec4<f32>(9.0, 20.0, 20.0, 20.0), vec4<f32>(20.0, 9.0, 20.0, 20.0), vec4<f32>(20.0, 20.0, 9.0, 20.0), vec4<f32>(20.0, 20.0, 20.0, 9.0)));
return ok;
}
+fn test_comma_b() -> bool {
+ var x: mat2x2<f32>;
+ var y: mat2x2<f32>;
+ x = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
+ y = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
+ return mat2x2f32_eq_mat2x2f32(x, y);
+}
fn main(coords: vec2<f32>) -> vec4<f32> {
var _0_ok: bool = true;
var _1_m1: mat2x2<f32> = mat2x2<f32>(vec2<f32>(1.0, 2.0), vec2<f32>(3.0, 4.0));
@@ -78,9 +85,16 @@
_0_ok = _0_ok && mat4x4f32_eq_mat4x4f32(_8_m11, mat4x4<f32>(vec4<f32>(9.0, 20.0, 20.0, 20.0), vec4<f32>(20.0, 9.0, 20.0, 20.0), vec4<f32>(20.0, 20.0, 9.0, 20.0), vec4<f32>(20.0, 20.0, 20.0, 9.0)));
var _skTemp0: vec4<f32>;
var _skTemp1: bool;
+ var _skTemp2: bool;
if _0_ok {
- let _skTemp2 = test_half_b();
- _skTemp1 = _skTemp2;
+ let _skTemp3 = test_half_b();
+ _skTemp2 = _skTemp3;
+ } else {
+ _skTemp2 = false;
+ }
+ if _skTemp2 {
+ let _skTemp4 = test_comma_b();
+ _skTemp1 = _skTemp4;
} else {
_skTemp1 = false;
}