From 88dcfef7164a2dbb65e4ebc9aaa3a22db5cc61e4 Mon Sep 17 00:00:00 2001 From: Diego De La Toba Date: Tue, 17 Feb 2026 14:49:46 -0800 Subject: [PATCH] Fix race condition in shader validation tests Combines GPU error scope validation and compilation info checks into a single sequential async operation to prevent non-deterministic error message ordering. This fixes intermittent test failures where error messages would appear in different orders across test runs due to parallel async execution. --- .../validation/shader_validation_test.ts | 57 +++++++++++-------- 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/src/webgpu/shader/validation/shader_validation_test.ts b/src/webgpu/shader/validation/shader_validation_test.ts index b1f2e3e375cb..9f392e29fa8b 100644 --- a/src/webgpu/shader/validation/shader_validation_test.ts +++ b/src/webgpu/shader/validation/shader_validation_test.ts @@ -62,18 +62,22 @@ export class ShaderValidationTest extends AllFeaturesMaxLimitsGPUTest { if (options?.autoSkipIfFeatureNotAvailable !== false) { skipIfCodeNeedsFeatureAndDeviceDoesNotHaveFeature(this, code); } - let shaderModule: GPUShaderModule; - this.expectGPUError( - 'validation', - () => { - shaderModule = this.device.createShaderModule({ code }); - }, - expectedResult !== true - ); - const error = new Error(); - this.eventualAsyncExpectation(async () => { - const compilationInfo = await shaderModule!.getCompilationInfo(); + this.eventualAsyncExpectation(async (niceStack: Error) => { + if (expectedResult !== true) { + this.device.pushErrorScope('validation'); + } + const shaderModule = this.device.createShaderModule({ code }); + + if (expectedResult !== true) { + const gpuError = await this.device.popErrorScope(); + if (!(gpuError instanceof GPUValidationError)) { + niceStack.message = `Expected validation error`; + this.rec.expectationFailed(niceStack); + } + } + + const compilationInfo = await shaderModule.getCompilationInfo(); // MAINTENANCE_TODO: Pretty-print error messages with source context. const messagesLog = @@ -83,6 +87,7 @@ export class ShaderValidationTest extends AllFeaturesMaxLimitsGPUTest { '\n\n---- shader ----\n' + code; + const error = new Error(); if (compilationInfo.messages.some(m => m.type === 'error')) { if (expectedResult) { error.message = `Unexpected compilationInfo 'error' message.\n` + messagesLog; @@ -124,7 +129,7 @@ export class ShaderValidationTest extends AllFeaturesMaxLimitsGPUTest { const error = new Error(); this.eventualAsyncExpectation(async () => { - const compilationInfo = await shaderModule!.getCompilationInfo(); + const compilationInfo = await shaderModule.getCompilationInfo(); // MAINTENANCE_TODO: Pretty-print error messages with source context. const messagesLog = compilationInfo.messages @@ -255,18 +260,21 @@ export class UniqueFeaturesAndLimitsShaderValidationTest extends UniqueFeaturesO * ``` */ expectCompileResult(expectedResult: boolean, code: string) { - let shaderModule: GPUShaderModule; - this.expectGPUError( - 'validation', - () => { - shaderModule = this.device.createShaderModule({ code }); - }, - expectedResult !== true - ); + this.eventualAsyncExpectation(async (niceStack: Error) => { + if (expectedResult !== true) { + this.device.pushErrorScope('validation'); + } + const shaderModule = this.device.createShaderModule({ code }); - const error = new Error(); - this.eventualAsyncExpectation(async () => { - const compilationInfo = await shaderModule!.getCompilationInfo(); + if (expectedResult !== true) { + const gpuError = await this.device.popErrorScope(); + if (!(gpuError instanceof GPUValidationError)) { + niceStack.message = `Expected validation error`; + this.rec.expectationFailed(niceStack); + } + } + + const compilationInfo = await shaderModule.getCompilationInfo(); // MAINTENANCE_TODO: Pretty-print error messages with source context. const messagesLog = @@ -276,6 +284,7 @@ export class UniqueFeaturesAndLimitsShaderValidationTest extends UniqueFeaturesO '\n\n---- shader ----\n' + code; + const error = new Error(); if (compilationInfo.messages.some(m => m.type === 'error')) { if (expectedResult) { error.message = `Unexpected compilationInfo 'error' message.\n` + messagesLog; @@ -317,7 +326,7 @@ export class UniqueFeaturesAndLimitsShaderValidationTest extends UniqueFeaturesO const error = new Error(); this.eventualAsyncExpectation(async () => { - const compilationInfo = await shaderModule!.getCompilationInfo(); + const compilationInfo = await shaderModule.getCompilationInfo(); // MAINTENANCE_TODO: Pretty-print error messages with source context. const messagesLog = compilationInfo.messages