diff options
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/shader/execution/memory_model/atomicity.spec.ts')
-rw-r--r-- | dom/webgpu/tests/cts/checkout/src/webgpu/shader/execution/memory_model/atomicity.spec.ts | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/shader/execution/memory_model/atomicity.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/execution/memory_model/atomicity.spec.ts new file mode 100644 index 0000000000..371eee5f92 --- /dev/null +++ b/dom/webgpu/tests/cts/checkout/src/webgpu/shader/execution/memory_model/atomicity.spec.ts @@ -0,0 +1,102 @@ +export const description = `Tests for the atomicity of atomic read-modify-write instructions.`; + +import { makeTestGroup } from '../../../../common/framework/test_group.js'; +import { GPUTest } from '../../../gpu_test.js'; + +import { + MemoryModelTestParams, + MemoryModelTester, + buildTestShader, + TestType, + buildResultShader, + ResultType, + MemoryType, +} from './memory_model_setup.js'; + +export const g = makeTestGroup(GPUTest); + +// A reasonable parameter set, determined heuristically. +const memoryModelTestParams: MemoryModelTestParams = { + workgroupSize: 256, + testingWorkgroups: 512, + maxWorkgroups: 1024, + shufflePct: 100, + barrierPct: 100, + memStressPct: 100, + memStressIterations: 1024, + memStressStoreFirstPct: 50, + memStressStoreSecondPct: 50, + preStressPct: 100, + preStressIterations: 1024, + preStressStoreFirstPct: 50, + preStressStoreSecondPct: 50, + scratchMemorySize: 2048, + stressLineSize: 64, + stressTargetLines: 2, + stressStrategyBalancePct: 50, + permuteFirst: 109, + permuteSecond: 419, + memStride: 4, + aliasedMemory: false, + numBehaviors: 4, +}; + +const storageMemoryTestCode = ` + let r0 = atomicAdd(&test_locations.value[x_0], 0u); + atomicStore(&test_locations.value[x_1], 2u); + atomicStore(&results.value[id_0].r0, r0); +`; + +const workgroupMemoryTestCode = ` + let r0 = atomicAdd(&wg_test_locations[x_0], 0u); + atomicStore(&wg_test_locations[x_1], 2u); + workgroupBarrier(); + atomicStore(&results.value[shuffled_workgroup * workgroupXSize + id_0].r0, r0); + atomicStore(&test_locations.value[shuffled_workgroup * workgroupXSize * stress_params.mem_stride * 2u + x_1], atomicLoad(&wg_test_locations[x_1])); +`; + +const resultCode = ` + if ((r0 == 0u && mem_x_0 == 2u)) { + atomicAdd(&test_results.seq0, 1u); + } else if ((r0 == 2u && mem_x_0 == 1u)) { + atomicAdd(&test_results.seq1, 1u); + } else if ((r0 == 0u && mem_x_0 == 1u)) { + atomicAdd(&test_results.weak, 1u); + } +`; + +g.test('atomicity') + .desc( + `Checks whether a store on one thread can interrupt an atomic RMW on a second thread. If the read returned by + the RMW instruction is the initial value of memory (0), but the final value in memory is 1, then the atomic write + in the second thread occurred in between the read and the write of the RMW. + ` + ) + .paramsSimple([ + { + memType: MemoryType.AtomicStorageClass, + testType: TestType.InterWorkgroup, + _testCode: storageMemoryTestCode, + }, + { + memType: MemoryType.AtomicStorageClass, + testType: TestType.IntraWorkgroup, + _testCode: storageMemoryTestCode, + }, + { + memType: MemoryType.AtomicWorkgroupClass, + testType: TestType.IntraWorkgroup, + _testCode: workgroupMemoryTestCode, + }, + ]) + .fn(async t => { + const testShader = buildTestShader(t.params._testCode, t.params.memType, t.params.testType); + const resultShader = buildResultShader(resultCode, t.params.testType, ResultType.FourBehavior); + const memModelTester = new MemoryModelTester( + t, + memoryModelTestParams, + testShader, + resultShader + ); + await memModelTester.run(10, 3); + }); |