diff --git a/src/webgpu/listing_meta.json b/src/webgpu/listing_meta.json index 57d60ee2d9e0..47fc70d51e56 100644 --- a/src/webgpu/listing_meta.json +++ b/src/webgpu/listing_meta.json @@ -2066,6 +2066,8 @@ "webgpu:shader,execution,statement,increment_decrement:vec4_element_decrement:*": { "subcaseMS": 5.300 }, "webgpu:shader,execution,statement,increment_decrement:vec4_element_increment:*": { "subcaseMS": 6.300 }, "webgpu:shader,execution,statement,phony:executes:*": { "subcaseMS": 129.949 }, + "webgpu:shader,execution,statement,swizzle_assignment:compound_eval_order:*": { "subcaseMS": 16.651 }, + "webgpu:shader,execution,statement,swizzle_assignment:eval_order:*": { "subcaseMS": 17.193 }, "webgpu:shader,execution,statement,swizzle_assignment:swizzle_assignment_vars:*": { "subcaseMS": 1200.970 }, "webgpu:shader,execution,statement,swizzle_assignment:swizzle_compound_assignment:*": { "subcaseMS": 0.091 }, "webgpu:shader,execution,value_init:array,nested:*": { "subcaseMS": 3004.523 }, diff --git a/src/webgpu/shader/execution/statement/swizzle_assignment.spec.ts b/src/webgpu/shader/execution/statement/swizzle_assignment.spec.ts index 421240f99133..b66f6bc2929e 100644 --- a/src/webgpu/shader/execution/statement/swizzle_assignment.spec.ts +++ b/src/webgpu/shader/execution/statement/swizzle_assignment.spec.ts @@ -7,6 +7,7 @@ import { keysOf } from '../../../../common/util/data_tables.js'; import { TypedArrayBufferView } from '../../../../common/util/util.js'; import { Float16Array } from '../../../../external/petamoriken/float16/float16.js'; import { AllFeaturesMaxLimitsGPUTest, GPUTest } from '../../../gpu_test.js'; +import { runFlowControlTest } from '../flow_control/harness.js'; export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); @@ -420,3 +421,76 @@ fn main() { }`; runSwizzleAssignmentTest(t, elemType, expected, wgsl); }); + +g.test('eval_order') + .desc( + 'Tests that the vec pointer on the lhs of a swizzle assignment is evaluated before the rhs, and the load of the lhs vec happens after rhs.' + ) + .fn(t => { + t.skipIfLanguageFeatureNotSupported('swizzle_assignment'); + runFlowControlTest(t, f => ({ + entrypoint: ` + arr[0] = vec4u(1, 1, 1, 1); + ${f.expect_order(0)} + arr[foo()].xy = bar(); + ${f.expect_order(3)} + if (all(arr[0] == vec4u(4, 5, 3, 8))) { + ${f.expect_order(4)} + } else { + ${f.expect_not_reached()} + } +`, + extra: ` +var arr : array; +fn foo() -> u32 { + ${f.expect_order(1)} + arr[0].x = 6; // overwritten by swizzle + arr[0].z = 7; // overwritten by bar() + arr[0].w = 8; // persists + return 0; +} +fn bar() -> vec2u { + ${f.expect_order(2)} + arr[0].z = 3; // persists + return vec2u(4, 5); // will set x,y +} +`, + })); + }); + +g.test('compound_eval_order') + .desc( + 'Tests that the lhs of a swizzle compound assignment is evaluated before the rhs, and another load of the lhs vec happens after rhs evaluation, without re-evaluating the pointer to the lhs vec.' + ) + .fn(t => { + t.skipIfLanguageFeatureNotSupported('swizzle_assignment'); + runFlowControlTest(t, f => ({ + entrypoint: ` + arr[0] = vec4u(1, 1, 1, 1); + ${f.expect_order(0)} + arr[foo()].xy += bar(); + ${f.expect_order(3)} + if (all(arr[0] == vec4u(10, 6, 3, 8))) { + ${f.expect_order(4)} + } else { + ${f.expect_not_reached()} + } +`, + extra: ` +var arr : array; +fn foo() -> u32 { + ${f.expect_order(1)} + arr[0].x = 6; // modifies x before add + arr[0].z = 7; // overwritten by bar() + arr[0].w = 8; // persists + return 0; +} +fn bar() -> vec2u { + ${f.expect_order(2)} + arr[0].x = 2; // no visible effect + arr[0].z = 3; // persists + return vec2u(4, 5); // will add to x,y +} +`, + })); + });