From d7d75446a160c1b833ef24b7bb759cba404eeb85 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Wed, 11 May 2022 11:50:06 -0700 Subject: [PATCH] Reland "Simplify device selection" with fix (#1386) REVERT AGAIN IF THIS CAUSES BREAKAGE * Revert "Revert "Simplify device selection" and dependent commits (#1384)" This reverts commit 0a1288f5e8262e900169795d742082bbc9d6ee22. * Free DeviceHolder even on TestFailedButDeviceReusable --- src/common/framework/fixture.ts | 15 +- src/common/internal/test_group.ts | 1 + src/common/util/util.ts | 11 + .../copyTextureToTexture.spec.ts | 12 +- .../command_buffer/image_copy.spec.ts | 24 +-- .../pipeline_output_targets.spec.ts | 12 +- .../api/operation/rendering/depth.spec.ts | 4 +- .../rendering/depth_clip_clamp.spec.ts | 8 +- .../api/operation/rendering/draw.spec.ts | 4 +- .../resource_init/texture_zero.spec.ts | 4 +- .../attachment_compatibility.spec.ts | 12 +- .../features/query_types.spec.ts | 4 +- .../features/texture_formats.spec.ts | 24 +-- .../api/validation/createBindGroup.spec.ts | 8 +- .../validation/createComputePipeline.spec.ts | 8 +- .../validation/createPipelineLayout.spec.ts | 4 +- .../validation/createRenderPipeline.spec.ts | 44 ++-- .../api/validation/createTexture.spec.ts | 60 +++--- src/webgpu/api/validation/createView.spec.ts | 8 +- .../encoding/beginRenderPass.spec.ts | 12 +- .../cmds/buffer_texture_copies.spec.ts | 12 +- .../encoding/cmds/clearBuffer.spec.ts | 4 +- .../encoding/cmds/compute_pass.spec.ts | 8 +- .../encoding/cmds/copyBufferToBuffer.spec.ts | 4 +- .../cmds/copyTextureToTexture.spec.ts | 20 +- .../cmds/render/indirect_draw.spec.ts | 4 +- .../cmds/render/setIndexBuffer.spec.ts | 4 +- .../encoding/cmds/render/setPipeline.spec.ts | 4 +- .../cmds/render/setVertexBuffer.spec.ts | 4 +- .../encoding/cmds/setBindGroup.spec.ts | 4 +- .../createRenderBundleEncoder.spec.ts | 8 +- .../encoding/queries/general.spec.ts | 18 +- .../encoding/queries/resolveQuerySet.spec.ts | 4 +- .../validation/encoding/render_bundle.spec.ts | 12 +- .../image_copy/buffer_related.spec.ts | 8 +- .../image_copy/layout_related.spec.ts | 16 +- .../image_copy/texture_related.spec.ts | 16 +- .../api/validation/query_set/create.spec.ts | 4 +- .../CopyExternalImageToTexture.spec.ts | 8 +- .../queue/destroyed/query_set.spec.ts | 2 +- .../api/validation/queue/submit.spec.ts | 4 +- .../api/validation/queue/writeBuffer.spec.ts | 4 +- .../validation/render_pass_descriptor.spec.ts | 4 +- .../texture/in_pass_encoder.spec.ts | 4 +- .../state/device_lost/destroy.spec.ts | 20 +- src/webgpu/examples.spec.ts | 8 +- src/webgpu/gpu_test.ts | 194 ++++++++---------- src/webgpu/util/device_pool.ts | 98 ++++----- .../web_platform/copyToTexture/canvas.spec.ts | 4 +- 49 files changed, 390 insertions(+), 393 deletions(-) diff --git a/src/common/framework/fixture.ts b/src/common/framework/fixture.ts index b88cfe0df8c6..ff3ab28e4506 100644 --- a/src/common/framework/fixture.ts +++ b/src/common/framework/fixture.ts @@ -32,9 +32,20 @@ export class SubcaseBatchState { return this._params; } - /** @internal MAINTENANCE_TODO: Make this not visible to test code? */ + /** + * Runs before the `.before()` function. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ async init() {} - /** @internal MAINTENANCE_TODO: Make this not visible to test code? */ + /** + * Runs between the `.before()` function and the subcases. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ + async postInit() {} + /** + * Runs after all subcases finish. + * @internal MAINTENANCE_TODO: Make this not visible to test code? + */ async finalize() {} } diff --git a/src/common/internal/test_group.ts b/src/common/internal/test_group.ts index cded41d01b3c..8b20641bb281 100644 --- a/src/common/internal/test_group.ts +++ b/src/common/internal/test_group.ts @@ -497,6 +497,7 @@ class RunCaseSpecific implements RunCase { if (this.beforeFn) { await this.beforeFn(sharedState); } + await sharedState.postInit(); let allPreviousSubcasesFinalizedPromise: Promise = Promise.resolve(); if (this.subcases) { diff --git a/src/common/util/util.ts b/src/common/util/util.ts index f0a907f0ce30..44fb6a6dc87d 100644 --- a/src/common/util/util.ts +++ b/src/common/util/util.ts @@ -117,6 +117,17 @@ export function raceWithRejectOnTimeout(p: Promise, ms: number, msg: strin return Promise.race([p, timeoutPromise]) as Promise; } +/** + * Returns a `Promise.reject()`, but also registers a dummy `.catch()` handler so it doesn't count + * as an uncaught promise rejection in the runtime. + */ +export function rejectWithoutUncaught(err: unknown): Promise { + const p = Promise.reject(err); + // Suppress uncaught promise rejection. + p.catch(() => {}); + return p; +} + /** * Makes a copy of a JS `object`, with the keys reordered into sorted order. */ diff --git a/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts b/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts index 24f6ebb013f9..1cfe8e2f2678 100644 --- a/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts +++ b/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts @@ -778,9 +778,9 @@ g.test('color_textures,compressed,non_array') .combine('srcCopyLevel', [0, 2]) .combine('dstCopyLevel', [0, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { srcFormat, dstFormat } = t.params; - await t.selectDeviceOrSkipTestCase([ + t.selectDeviceOrSkipTestCase([ kTextureFormatInfo[srcFormat].feature, kTextureFormatInfo[dstFormat].feature, ]); @@ -932,10 +932,10 @@ g.test('color_textures,compressed,array') .combine('srcCopyLevel', [0, 2]) .combine('dstCopyLevel', [0, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { srcFormat, dstFormat } = t.params; - await t.selectDeviceOrSkipTestCase([ + t.selectDeviceOrSkipTestCase([ kTextureFormatInfo[srcFormat].feature, kTextureFormatInfo[dstFormat].feature, ]); @@ -1116,9 +1116,9 @@ g.test('copy_depth_stencil') ); }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { diff --git a/src/webgpu/api/operation/command_buffer/image_copy.spec.ts b/src/webgpu/api/operation/command_buffer/image_copy.spec.ts index 24f77db53a96..489a8ca46e8a 100644 --- a/src/webgpu/api/operation/command_buffer/image_copy.spec.ts +++ b/src/webgpu/api/operation/command_buffer/image_copy.spec.ts @@ -1287,9 +1287,9 @@ bytes in copy works for every format. return kRowsPerImageAndBytesPerRowParams.copySizes; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -1383,9 +1383,9 @@ works for every format with 2d and 2d-array textures. .combine('copyDepth', kOffsetsAndSizesParams.copyDepth) // 2d and 2d-array textures .unless(p => p.dimension === '1d' && p.copyDepth !== 1) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -1462,9 +1462,9 @@ for all formats. We pass origin and copyExtent as [number, number, number].` .combine('coordinateToTest', [0, 1, 2] as const) .unless(p => p.dimension === '1d' && p.coordinateToTest !== 0) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -1661,9 +1661,9 @@ TODO: Make a variant for depth-stencil formats. ]) .expand('textureSize', generateTestTextureSizes) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -1828,9 +1828,9 @@ aspect and copyTextureToBuffer() with depth aspect. }) .combine('mipLevel', [0, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -1919,9 +1919,9 @@ copyTextureToBuffer() with depth aspect. .combine('copyDepth', kOffsetsAndSizesParams.copyDepth) .combine('mipLevel', [0, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { diff --git a/src/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.ts b/src/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.ts index 9026506d8518..4515da9efa01 100644 --- a/src/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.ts +++ b/src/webgpu/api/operation/render_pipeline/pipeline_output_targets.spec.ts @@ -151,9 +151,9 @@ g.test('color,attachments') .combine('attachmentCount', [2, 3, 4]) .expand('emptyAttachmentId', p => range(p.attachmentCount, i => i)) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, attachmentCount, emptyAttachmentId } = t.params; @@ -254,9 +254,9 @@ g.test('color,component_count') .combine('componentCount', [1, 2, 3, 4]) .filter(x => x.componentCount >= kTexelRepresentationInfo[x.format].componentOrder.length) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, componentCount } = t.params; @@ -459,9 +459,9 @@ The attachment has a load value of [1, 0, 0, 1] ] as const) .filter(x => x.output.length >= kTexelRepresentationInfo[x.format].componentOrder.length) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { diff --git a/src/webgpu/api/operation/rendering/depth.spec.ts b/src/webgpu/api/operation/rendering/depth.spec.ts index b77f20d14f32..a740316eb9c8 100644 --- a/src/webgpu/api/operation/rendering/depth.spec.ts +++ b/src/webgpu/api/operation/rendering/depth.spec.ts @@ -76,8 +76,8 @@ g.test('depth_compare_func') { depthCompare: 'always', depthClearValue: 0.0, _expected: triangleColor }, ] as const) ) - .beforeAllSubcases(async t => { - await t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); + .beforeAllSubcases(t => { + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); }) .fn(async t => { const { depthCompare, depthClearValue, _expected, format } = t.params; diff --git a/src/webgpu/api/operation/rendering/depth_clip_clamp.spec.ts b/src/webgpu/api/operation/rendering/depth_clip_clamp.spec.ts index 431bbdf1fe05..3465f72c92b1 100644 --- a/src/webgpu/api/operation/rendering/depth_clip_clamp.spec.ts +++ b/src/webgpu/api/operation/rendering/depth_clip_clamp.spec.ts @@ -41,10 +41,10 @@ have unexpected values then get drawn to the color buffer, which is later checke .combine('writeDepth', [false, true]) .combine('multisampled', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase([ + t.selectDeviceOrSkipTestCase([ t.params.unclippedDepth ? 'depth-clip-control' : undefined, info.feature, ]); @@ -354,10 +354,10 @@ to be empty.` .combine('unclippedDepth', [false, true]) .combine('multisampled', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase([ + t.selectDeviceOrSkipTestCase([ t.params.unclippedDepth ? 'depth-clip-control' : undefined, info.feature, ]); diff --git a/src/webgpu/api/operation/rendering/draw.spec.ts b/src/webgpu/api/operation/rendering/draw.spec.ts index 3cdd92dadd0a..81d7615b6595 100644 --- a/src/webgpu/api/operation/rendering/draw.spec.ts +++ b/src/webgpu/api/operation/rendering/draw.spec.ts @@ -50,9 +50,9 @@ Params: .expand('index_buffer_offset', p => (p.indexed ? ([0, 16] as const) : [undefined])) .expand('base_vertex', p => (p.indexed ? ([0, 9] as const) : [undefined])) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { if (t.params.first_instance > 0 && t.params.indirect) { - await t.selectDeviceOrSkipTestCase('indirect-first-instance'); + t.selectDeviceOrSkipTestCase('indirect-first-instance'); } }) .fn(async t => { diff --git a/src/webgpu/api/operation/resource_init/texture_zero.spec.ts b/src/webgpu/api/operation/resource_init/texture_zero.spec.ts index e99331b2192a..8dd3df3441c0 100644 --- a/src/webgpu/api/operation/resource_init/texture_zero.spec.ts +++ b/src/webgpu/api/operation/resource_init/texture_zero.spec.ts @@ -577,8 +577,8 @@ export const g = makeTestGroup(TextureZeroInitTest); g.test('uninitialized_texture_is_zero') .params(kTestParams) - .beforeAllSubcases(async t => { - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[t.params.format].feature); + .beforeAllSubcases(t => { + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[t.params.format].feature); }) .fn(async t => { const usage = getRequiredTextureUsage( diff --git a/src/webgpu/api/validation/attachment_compatibility.spec.ts b/src/webgpu/api/validation/attachment_compatibility.spec.ts index 7c33824e2809..4a58644594f6 100644 --- a/src/webgpu/api/validation/attachment_compatibility.spec.ts +++ b/src/webgpu/api/validation/attachment_compatibility.spec.ts @@ -275,9 +275,9 @@ g.test('render_pass_and_bundle,depth_format') filterFormatsByFeature(bundleFeature, kDepthStencilAttachmentFormats) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { passFeature, bundleFeature } = t.params; - await t.selectDeviceOrSkipTestCase([passFeature, bundleFeature]); + t.selectDeviceOrSkipTestCase([passFeature, bundleFeature]); }) .fn(async t => { const { passFormat, bundleFormat } = t.params; @@ -431,9 +431,9 @@ Test that the depth attachment format in render passes or bundles match the pipe filterFormatsByFeature(pipelineFormatFeature, kDepthStencilAttachmentFormats) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { encoderFormatFeature, pipelineFormatFeature } = t.params; - await t.selectDeviceOrSkipTestCase([encoderFormatFeature, pipelineFormatFeature]); + t.selectDeviceOrSkipTestCase([encoderFormatFeature, pipelineFormatFeature]); }) .fn(async t => { const { encoderType, encoderFormat, pipelineFormat } = t.params; @@ -503,8 +503,8 @@ Test that the depth stencil read only state in render passes or bundles is compa return true; }) ) - .beforeAllSubcases(async t => { - await t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); + .beforeAllSubcases(t => { + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/capability_checks/features/query_types.spec.ts b/src/webgpu/api/validation/capability_checks/features/query_types.spec.ts index c014ca605101..09d176c1cc95 100644 --- a/src/webgpu/api/validation/capability_checks/features/query_types.spec.ts +++ b/src/webgpu/api/validation/capability_checks/features/query_types.spec.ts @@ -25,7 +25,7 @@ As of this writing, the spec needs to be fixed as well. .combine('type', ['occlusion', 'timestamp'] as const) .combine('timestampQueryEnable', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { timestampQueryEnable } = t.params; const requiredFeatures: GPUFeatureName[] = []; @@ -33,7 +33,7 @@ As of this writing, the spec needs to be fixed as well. requiredFeatures.push('timestamp-query'); } - await t.selectDeviceOrSkipTestCase({ requiredFeatures }); + t.selectDeviceOrSkipTestCase({ requiredFeatures }); }) .fn(async t => { const { type, timestampQueryEnable } = t.params; diff --git a/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts b/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts index 0cc83a3f16c7..5e5ce262abde 100644 --- a/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts +++ b/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts @@ -30,12 +30,12 @@ g.test('texture_descriptor') .params(u => u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { @@ -66,12 +66,12 @@ g.test('storage_texture_binding_layout') .filter(t => kTextureFormatInfo[t.format].storage) .combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { @@ -107,12 +107,12 @@ g.test('color_target_state') .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color) .combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { @@ -162,12 +162,12 @@ g.test('depth_stencil_state') ) .combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { @@ -218,12 +218,12 @@ g.test('render_bundle_encoder_descriptor_color_format') .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color) .combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { @@ -253,12 +253,12 @@ g.test('render_bundle_encoder_descriptor_depth_stencil_format') ) .combine('enable_required_feature', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format, enable_required_feature } = t.params; const formatInfo = kTextureFormatInfo[format]; if (enable_required_feature) { - await t.selectDeviceOrSkipTestCase(formatInfo.feature); + t.selectDeviceOrSkipTestCase(formatInfo.feature); } }) .fn(async t => { diff --git a/src/webgpu/api/validation/createBindGroup.spec.ts b/src/webgpu/api/validation/createBindGroup.spec.ts index 515e479fb8d9..7c9fbbb870fe 100644 --- a/src/webgpu/api/validation/createBindGroup.spec.ts +++ b/src/webgpu/api/validation/createBindGroup.spec.ts @@ -499,8 +499,8 @@ g.test('bind_group_layout,device_mismatch') 'Tests createBindGroup cannot be called with a bind group layout created from another device' ) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const mismatched = t.params.mismatched; @@ -556,8 +556,8 @@ g.test('binding_resources,device_mismatch') { resource0Mismatched: false, resource1Mismatched: true }, ]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { entry, resource0Mismatched, resource1Mismatched } = t.params; diff --git a/src/webgpu/api/validation/createComputePipeline.spec.ts b/src/webgpu/api/validation/createComputePipeline.spec.ts index 7dfa744cfa8e..06a782015732 100644 --- a/src/webgpu/api/validation/createComputePipeline.spec.ts +++ b/src/webgpu/api/validation/createComputePipeline.spec.ts @@ -179,8 +179,8 @@ g.test('pipeline_layout,device_mismatch') 'Tests createComputePipeline(Async) cannot be called with a pipeline layout created from another device' ) .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { isAsync, mismatched } = t.params; @@ -204,8 +204,8 @@ g.test('shader_module,device_mismatch') 'Tests createComputePipeline(Async) cannot be called with a shader module created from another device' ) .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { isAsync, mismatched } = t.params; diff --git a/src/webgpu/api/validation/createPipelineLayout.spec.ts b/src/webgpu/api/validation/createPipelineLayout.spec.ts index 51209b352c5b..9dfc56554c9e 100644 --- a/src/webgpu/api/validation/createPipelineLayout.spec.ts +++ b/src/webgpu/api/validation/createPipelineLayout.spec.ts @@ -117,8 +117,8 @@ g.test('bind_group_layouts,device_mismatch') { layout0Mismatched: true, layout1Mismatched: false }, { layout0Mismatched: false, layout1Mismatched: true }, ]) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { layout0Mismatched, layout1Mismatched } = t.params; diff --git a/src/webgpu/api/validation/createRenderPipeline.spec.ts b/src/webgpu/api/validation/createRenderPipeline.spec.ts index 16eaa1b9d12a..d4970338bc43 100644 --- a/src/webgpu/api/validation/createRenderPipeline.spec.ts +++ b/src/webgpu/api/validation/createRenderPipeline.spec.ts @@ -248,10 +248,10 @@ g.test('at_least_one_color_state_is_required_for_complete_pipeline') g.test('color_formats_must_be_renderable') .desc(`TODO: review and add description; shorten name`) .params(u => u.combine('isAsync', [false, true]).combine('format', kTextureFormats)) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format } = t.params; @@ -265,10 +265,10 @@ g.test('color_formats_must_be_renderable') g.test('depth_stencil_state,format') .desc(`The texture format in depthStencilState must be a depth/stencil format`) .params(u => u.combine('isAsync', [false, true]).combine('format', kTextureFormats)) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format } = t.params; @@ -289,10 +289,10 @@ g.test('depth_stencil_state,depth_aspect,depth_test') .combine('format', kDepthStencilFormats) .combine('depthCompare', [undefined, ...kCompareFunctions]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format, depthCompare } = t.params; @@ -316,10 +316,10 @@ g.test('depth_stencil_state,depth_aspect,depth_write') .combine('format', kDepthStencilFormats) .combine('depthWriteEnabled', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format, depthWriteEnabled } = t.params; @@ -342,10 +342,10 @@ g.test('depth_stencil_state,stencil_aspect,stencil_test') .combine('face', ['front', 'back'] as const) .combine('compare', [undefined, ...kCompareFunctions]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format, face, compare } = t.params; @@ -380,10 +380,10 @@ g.test('depth_stencil_state,stencil_aspect,stencil_write') ] as const) .combine('op', [undefined, ...kStencilOperations]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format, faceAndOpType, op } = t.params; @@ -457,10 +457,10 @@ g.test('pipeline_output_targets') .combine('sampleType', ['float', 'uint', 'sint'] as const) .combine('componentCount', [1, 2, 3, 4]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format, sampleType, componentCount } = t.params; @@ -546,10 +546,10 @@ g.test('pipeline_output_targets,blend') }, ] as const) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const sampleType = 'float'; @@ -604,10 +604,10 @@ Tests if blending is used, the target's format must be blendable (support "float .params(u => u.combine('isAsync', [false, true]).combine('format', kRenderableColorTextureFormats) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { isAsync, format } = t.params; @@ -697,8 +697,8 @@ g.test('pipeline_layout,device_mismatch') 'Tests createRenderPipeline(Async) cannot be called with a pipeline layout created from another device' ) .paramsSubcasesOnly(u => u.combine('isAsync', [true, false]).combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { isAsync, mismatched } = t.params; @@ -740,8 +740,8 @@ g.test('shader_module,device_mismatch') { vertex_mismatched: false, fragment_mismatched: true, _success: false }, ]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { isAsync, vertex_mismatched, fragment_mismatched, _success } = t.params; diff --git a/src/webgpu/api/validation/createTexture.spec.ts b/src/webgpu/api/validation/createTexture.spec.ts index 6bd21a99b556..769cc9ff43f2 100644 --- a/src/webgpu/api/validation/createTexture.spec.ts +++ b/src/webgpu/api/validation/createTexture.spec.ts @@ -49,10 +49,10 @@ g.test('zero_size') // Filter out incompatible dimension type and format combinations. .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format)) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, zeroArgument, format } = t.params; @@ -100,10 +100,10 @@ g.test('dimension_type_and_format_compatibility') .params(u => u.combine('dimension', [undefined, ...kTextureDimensions]).combine('format', kTextureFormats) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format } = t.params; @@ -137,10 +137,10 @@ g.test('mipLevelCount,format') .combine('largestDimension', [0, 1, 2]) .unless(({ dimension, largestDimension }) => dimension === '1d' && largestDimension > 0) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, mipLevelCount, largestDimension } = t.params; @@ -215,10 +215,10 @@ g.test('mipLevelCount,bound_check') size[1] % kTextureFormatInfo[format].blockHeight !== 0) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, size, dimension } = t.params; @@ -267,10 +267,10 @@ g.test('sampleCount,various_sampleCount_with_all_formats') .beginSubcases() .combine('sampleCount', [0, 1, 2, 4, 8, 16, 32, 256]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, sampleCount, format } = t.params; @@ -324,10 +324,10 @@ g.test('sampleCount,valid_sampleCount_with_other_parameter_varies') ); }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, sampleCount, format, mipLevelCount, arrayLayerCount, usage } = t.params; @@ -376,10 +376,10 @@ g.test('texture_size,default_value_and_smallest_size,uncompressed_format') // Filter out incompatible dimension type and format combinations. .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format)) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, size } = t.params; @@ -417,10 +417,10 @@ g.test('texture_size,default_value_and_smallest_size,compressed_format') ]; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, size, _success } = t.params; @@ -452,10 +452,10 @@ g.test('texture_size,1d_texture') .combine('height', [1, 2]) .combine('depthOrArrayLayers', [1, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, width, height, depthOrArrayLayers } = t.params; @@ -496,10 +496,10 @@ g.test('texture_size,2d_texture,uncompressed_format') [1, 1, kLimitInfo.maxTextureArrayLayers.default + 1], ]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, size } = t.params; @@ -564,10 +564,10 @@ g.test('texture_size,2d_texture,compressed_format') ]; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, size } = t.params; @@ -615,10 +615,10 @@ g.test('texture_size,3d_texture,uncompressed_format') [1, 1, kLimitInfo.maxTextureDimension3D.default + 1], ]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, size } = t.params; @@ -683,13 +683,13 @@ g.test('texture_size,3d_texture,compressed_format') ]; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { // Compressed formats are not supported in 3D in WebGPU v1 because they are complicated but not very useful for now. throw new SkipTestCase('Compressed 3D texture is not supported'); const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, size } = t.params; @@ -734,10 +734,10 @@ g.test('texture_usage') // Filter out incompatible dimension type and format combinations. .filter(({ dimension, format }) => textureDimensionAndFormatCompatible(dimension, format)) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; const info = kTextureFormatInfo[format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { dimension, format, usage0, usage1 } = t.params; @@ -785,9 +785,9 @@ g.test('viewFormats') filterFormatsByFeature(viewFormatFeature, kTextureFormats) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { formatFeature, viewFormatFeature } = t.params; - await t.selectDeviceOrSkipTestCase([formatFeature, viewFormatFeature]); + t.selectDeviceOrSkipTestCase([formatFeature, viewFormatFeature]); }) .fn(async t => { const { format, viewFormat } = t.params; diff --git a/src/webgpu/api/validation/createView.spec.ts b/src/webgpu/api/validation/createView.spec.ts index 3b4a8529b884..58dfbabdae17 100644 --- a/src/webgpu/api/validation/createView.spec.ts +++ b/src/webgpu/api/validation/createView.spec.ts @@ -44,9 +44,9 @@ g.test('format') ) .combine('useViewFormatList', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { textureFormatFeature, viewFormatFeature } = t.params; - await t.selectDeviceOrSkipTestCase([textureFormatFeature, viewFormatFeature]); + t.selectDeviceOrSkipTestCase([textureFormatFeature, viewFormatFeature]); }) .fn(async t => { const { textureFormat, viewFormat, useViewFormatList } = t.params; @@ -119,9 +119,9 @@ g.test('aspect') .combine('format', kTextureFormats) .combine('aspect', kTextureAspects) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { format, aspect } = t.params; diff --git a/src/webgpu/api/validation/encoding/beginRenderPass.spec.ts b/src/webgpu/api/validation/encoding/beginRenderPass.spec.ts index fc1d82fe3ea9..0f0069a322b0 100644 --- a/src/webgpu/api/validation/encoding/beginRenderPass.spec.ts +++ b/src/webgpu/api/validation/encoding/beginRenderPass.spec.ts @@ -60,8 +60,8 @@ g.test('color_attachments,device_mismatch') target1Mismatched: true, }, ]) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { view0Mismatched, target0Mismatched, view1Mismatched, target1Mismatched } = t.params; @@ -109,8 +109,8 @@ g.test('depth_stencil_attachment,device_mismatch') 'Tests beginRenderPass cannot be called with a depth stencil attachment whose texture view is created from another device' ) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; @@ -148,8 +148,8 @@ g.test('occlusion_query_set,device_mismatch') 'Tests beginRenderPass cannot be called with an occlusion query set created from another device' ) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/buffer_texture_copies.spec.ts b/src/webgpu/api/validation/encoding/cmds/buffer_texture_copies.spec.ts index 815b3666b5e8..170a7bce146d 100644 --- a/src/webgpu/api/validation/encoding/cmds/buffer_texture_copies.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/buffer_texture_copies.spec.ts @@ -71,9 +71,9 @@ g.test('depth_stencil_format,copy_usage_and_aspect') .beginSubcases() .combine('aspect', ['all', 'depth-only', 'stencil-only'] as const) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { format, aspect } = t.params; @@ -136,9 +136,9 @@ g.test('depth_stencil_format,copy_buffer_size') { width: 4, height: 4, depthOrArrayLayers: 3 }, ]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { format, aspect, copyType, copySize } = t.params; @@ -243,9 +243,9 @@ g.test('depth_stencil_format,copy_buffer_offset') .beginSubcases() .combine('offset', [1, 2, 4, 6, 8]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { format, aspect, copyType, offset } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/clearBuffer.spec.ts b/src/webgpu/api/validation/encoding/cmds/clearBuffer.spec.ts index 0a0444ccaa13..8d234e311bf3 100644 --- a/src/webgpu/api/validation/encoding/cmds/clearBuffer.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/clearBuffer.spec.ts @@ -57,8 +57,8 @@ g.test('buffer_state') g.test('buffer,device_mismatch') .desc(`Tests clearBuffer cannot be called with buffer created from another device.`) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/compute_pass.spec.ts b/src/webgpu/api/validation/encoding/cmds/compute_pass.spec.ts index a1e1a08533cd..bb6161b9b2b1 100644 --- a/src/webgpu/api/validation/encoding/cmds/compute_pass.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/compute_pass.spec.ts @@ -65,8 +65,8 @@ setPipeline should generate an error iff using an 'invalid' pipeline. g.test('pipeline,device_mismatch') .desc('Tests setPipeline cannot be called with a compute pipeline created from another device') .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; @@ -182,8 +182,8 @@ g.test('indirect_dispatch_buffer,device_mismatch') `Tests dispatchWorkgroupsIndirect cannot be called with an indirect buffer created from another device` ) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.ts b/src/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.ts index a9b70032bb61..12b634b0e16d 100644 --- a/src/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.ts @@ -102,8 +102,8 @@ g.test('buffer,device_mismatch') { srcMismatched: true, dstMismatched: false }, { srcMismatched: false, dstMismatched: true }, ] as const) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { srcMismatched, dstMismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.ts b/src/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.ts index 3365c4826a99..bd946dd9f95f 100644 --- a/src/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.ts @@ -119,8 +119,8 @@ g.test('texture,device_mismatch') { srcMismatched: true, dstMismatched: false }, { srcMismatched: false, dstMismatched: true }, ] as const) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { srcMismatched, dstMismatched } = t.params; @@ -358,9 +358,9 @@ Test the formats of textures in copyTextureToTexture must be copy-compatible. filterFormatsByFeature(dstFormatFeature, kTextureFormats) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { srcFormatFeature, dstFormatFeature } = t.params; - await t.selectDeviceOrSkipTestCase([srcFormatFeature, dstFormatFeature]); + t.selectDeviceOrSkipTestCase([srcFormatFeature, dstFormatFeature]); }) .fn(async t => { const { srcFormat, dstFormat } = t.params; @@ -434,9 +434,9 @@ Note: this is only tested for 2D textures as it is the only dimension compatible .combine('srcCopyLevel', [1, 2]) .combine('dstCopyLevel', [0, 1]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { @@ -696,9 +696,9 @@ Test the validations on the member 'aspect' of GPUImageCopyTexture in CopyTextur .combine('sourceAspect', ['all', 'depth-only', 'stencil-only'] as const) .combine('destinationAspect', ['all', 'depth-only', 'stencil-only'] as const) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { format, sourceAspect, destinationAspect } = t.params; @@ -776,9 +776,9 @@ TODO: Express the offsets in "block size" so as to be able to test non-4x4 compr .combine('srcCopyLevel', [0, 1, 2]) .combine('dstCopyLevel', [0, 1, 2]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { format, dimension, copyBoxOffsets, srcCopyLevel, dstCopyLevel } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.ts b/src/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.ts index ec3f23b14e0f..0833fcf36e91 100644 --- a/src/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/render/indirect_draw.spec.ts @@ -55,8 +55,8 @@ g.test('indirect_buffer,device_mismatch') 'Tests draw(Indexed)Indirect cannot be called with an indirect buffer created from another device' ) .paramsSubcasesOnly(kIndirectDrawTestParams.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { encoderType, indexed, mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.ts b/src/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.ts index b6476d68fa44..283d40afd7a1 100644 --- a/src/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/render/setIndexBuffer.spec.ts @@ -33,8 +33,8 @@ Tests index buffer must be valid. g.test('index_buffer,device_mismatch') .desc('Tests setIndexBuffer cannot be called with an index buffer created from another device') .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { encoderType, mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.ts b/src/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.ts index 08c0e4a75e59..bf53a61f207b 100644 --- a/src/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/render/setPipeline.spec.ts @@ -31,8 +31,8 @@ Tests setPipeline should generate an error iff using an 'invalid' pipeline. g.test('pipeline,device_mismatch') .desc('Tests setPipeline cannot be called with a render pipeline created from another device') .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { encoderType, mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.ts b/src/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.ts index 9a53a59bb2af..2828438a15d8 100644 --- a/src/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/render/setVertexBuffer.spec.ts @@ -59,8 +59,8 @@ Tests vertex buffer must be valid. g.test('vertex_buffer,device_mismatch') .desc('Tests setVertexBuffer cannot be called with a vertex buffer created from another device') .paramsSubcasesOnly(kRenderEncodeTypeParams.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { encoderType, mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/cmds/setBindGroup.spec.ts b/src/webgpu/api/validation/encoding/cmds/setBindGroup.spec.ts index ab5bc53aa8d0..707fe14d8655 100644 --- a/src/webgpu/api/validation/encoding/cmds/setBindGroup.spec.ts +++ b/src/webgpu/api/validation/encoding/cmds/setBindGroup.spec.ts @@ -140,8 +140,8 @@ g.test('bind_group,device_mismatch') .combine('useU32Array', [true, false]) .combine('mismatched', [true, false]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { encoderType, useU32Array, mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.ts b/src/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.ts index 41914857e040..e7a2e06ada05 100644 --- a/src/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.ts +++ b/src/webgpu/api/validation/encoding/createRenderBundleEncoder.spec.ts @@ -68,9 +68,9 @@ g.test('valid_texture_formats') .beginSubcases() .combine('attachment', ['color', 'depthStencil']) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(format); + t.selectDeviceForTextureFormatOrSkipTestCase(format); }) .fn(async t => { const { format, attachment } = t.params; @@ -119,9 +119,9 @@ g.test('depth_stencil_readonly') .combine('depthReadOnly', [false, true]) .combine('stencilReadOnly', [false, true]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { depthStencilFormat } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase(depthStencilFormat); + t.selectDeviceForTextureFormatOrSkipTestCase(depthStencilFormat); }) .fn(async t => { const { depthStencilFormat, depthReadOnly, stencilReadOnly } = t.params; diff --git a/src/webgpu/api/validation/encoding/queries/general.spec.ts b/src/webgpu/api/validation/encoding/queries/general.spec.ts index 7e1962e2e956..077e3bccc76f 100644 --- a/src/webgpu/api/validation/encoding/queries/general.spec.ts +++ b/src/webgpu/api/validation/encoding/queries/general.spec.ts @@ -24,10 +24,10 @@ Tests that set occlusion query set with all types in render pass descriptor: ` ) .params(u => u.combine('type', [undefined, ...kQueryTypes])) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { type } = t.params; if (type) { - await t.selectDeviceForQueryTypeOrSkipTestCase(type); + t.selectDeviceForQueryTypeOrSkipTestCase(type); } }) .fn(async t => { @@ -88,10 +88,10 @@ Tests that write timestamp to all types of query set on all possible encoders: .beginSubcases() .expand('queryIndex', p => (p.type === 'timestamp' ? [0, 2] : [0])) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { type } = t.params; if (type) { - await t.selectDeviceForQueryTypeOrSkipTestCase(type); + t.selectDeviceForQueryTypeOrSkipTestCase(type); } }) .fn(async t => { @@ -113,8 +113,8 @@ Tests that write timestamp to a invalid query set that failed during creation: ` ) .paramsSubcasesOnly(u => u.combine('querySetState', ['valid', 'invalid'] as const)) - .beforeAllSubcases(async t => { - await t.selectDeviceForQueryTypeOrSkipTestCase('timestamp'); + .beforeAllSubcases(t => { + t.selectDeviceForQueryTypeOrSkipTestCase('timestamp'); }) .fn(async t => { const { querySetState } = t.params; @@ -132,9 +132,9 @@ Tests that write timestamp to a invalid query set that failed during creation: g.test('timestamp_query,device_mismatch') .desc('Tests writeTimestamp cannot be called with a query set created from another device') .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectDeviceForQueryTypeOrSkipTestCase('timestamp'); - await t.selectMismatchedDeviceOrSkipTestCase('timestamp-query'); + .beforeAllSubcases(t => { + t.selectDeviceForQueryTypeOrSkipTestCase('timestamp'); + t.selectMismatchedDeviceOrSkipTestCase('timestamp-query'); }) .fn(async t => { const { mismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.ts b/src/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.ts index d9f0469cb791..9214190d7912 100644 --- a/src/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.ts +++ b/src/webgpu/api/validation/encoding/queries/resolveQuerySet.spec.ts @@ -153,8 +153,8 @@ g.test('query_set_buffer,device_mismatch') { querySetMismatched: true, bufferMismatched: false }, { querySetMismatched: false, bufferMismatched: true }, ] as const) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { querySetMismatched, bufferMismatched } = t.params; diff --git a/src/webgpu/api/validation/encoding/render_bundle.spec.ts b/src/webgpu/api/validation/encoding/render_bundle.spec.ts index c8e5d0712280..650152aebdcf 100644 --- a/src/webgpu/api/validation/encoding/render_bundle.spec.ts +++ b/src/webgpu/api/validation/encoding/render_bundle.spec.ts @@ -34,8 +34,8 @@ g.test('device_mismatch') { bundle0Mismatched: true, bundle1Mismatched: false }, { bundle0Mismatched: false, bundle1Mismatched: true }, ]) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { bundle0Mismatched, bundle1Mismatched } = t.params; @@ -131,9 +131,9 @@ g.test('depth_stencil_formats_mismatch') { bundleFormat: 'stencil8', passFormat: 'depth24plus-stencil8' }, ] as const) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { bundleFormat, passFormat } = t.params; - await t.selectDeviceForTextureFormatOrSkipTestCase([bundleFormat, passFormat]); + t.selectDeviceForTextureFormatOrSkipTestCase([bundleFormat, passFormat]); }) .fn(async t => { const { bundleFormat, passFormat } = t.params; @@ -184,8 +184,8 @@ g.test('depth_stencil_readonly_mismatch') return true; }) ) - .beforeAllSubcases(async t => { - await t.selectDeviceForTextureFormatOrSkipTestCase(t.params.depthStencilFormat); + .beforeAllSubcases(t => { + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.depthStencilFormat); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/image_copy/buffer_related.spec.ts b/src/webgpu/api/validation/image_copy/buffer_related.spec.ts index 06c051b856df..3b0b8ec1299f 100644 --- a/src/webgpu/api/validation/image_copy/buffer_related.spec.ts +++ b/src/webgpu/api/validation/image_copy/buffer_related.spec.ts @@ -62,8 +62,8 @@ g.test('buffer,device_mismatch') .paramsSubcasesOnly(u => u.combine('method', ['CopyB2T', 'CopyT2B'] as const).combine('mismatched', [true, false]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { method, mismatched } = t.params; @@ -180,9 +180,9 @@ Test that bytesPerRow must be a multiple of 256 for CopyB2T and CopyT2B if it is (bytesPerRow !== undefined && bytesPerRow >= kTextureFormatInfo[format].bytesPerBlock) ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/image_copy/layout_related.spec.ts b/src/webgpu/api/validation/image_copy/layout_related.spec.ts index c2d7b06b8fc0..ac060bc54f6a 100644 --- a/src/webgpu/api/validation/image_copy/layout_related.spec.ts +++ b/src/webgpu/api/validation/image_copy/layout_related.spec.ts @@ -177,9 +177,9 @@ Test the computation of requiredBytesInCopy by computing the minimum data size f return [p._offsetMultiplier * info.bytesPerBlock]; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -249,9 +249,9 @@ Test that rowsPerImage has no alignment constraints. // Copy height is info.blockHeight, so rowsPerImage must be equal or greater than it. .filter(({ rowsPerImage, format }) => rowsPerImage >= kTextureFormatInfo[format].blockHeight) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { rowsPerImage, format, method } = t.params; @@ -291,9 +291,9 @@ Test the alignment requirement on the linear data offset (block size, or 4 for d .beginSubcases() .expand('offset', texelBlockAlignmentTestExpanderForOffset) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { format, offset, method } = t.params; @@ -395,9 +395,9 @@ Test that bytesPerRow, if specified must be big enough for a full copy row. ]; }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/image_copy/texture_related.spec.ts b/src/webgpu/api/validation/image_copy/texture_related.spec.ts index a72a814effa4..59efd2943c15 100644 --- a/src/webgpu/api/validation/image_copy/texture_related.spec.ts +++ b/src/webgpu/api/validation/image_copy/texture_related.spec.ts @@ -70,8 +70,8 @@ g.test('texture,device_mismatch') .paramsSubcasesOnly(u => u.combine('method', kImageCopyTypes).combine('mismatched', [true, false]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { method, mismatched } = t.params; @@ -255,9 +255,9 @@ Test the copy must be a full subresource if the texture's format is depth/stenci // need to examine depth dimension via copyDepthModifier to determine whether it is a full copy for a 3D texture. .expand('copyDepthModifier', ({ dimension: d }) => (d === '3d' ? [0, -1] : [0])) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -345,9 +345,9 @@ Test that the texture copy origin must be aligned to the format's block size. .unless(p => p.dimension === '1d' && p.coordinateToTest !== 'x') .expand('valueToCoordinate', texelBlockAlignmentTestExpanderForValueToCoordinate) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { @@ -408,9 +408,9 @@ Test that the copy size must be aligned to the texture's format's block size. .unless(p => p.dimension === '1d' && p.coordinateToTest !== 'width') .expand('valueToCoordinate', texelBlockAlignmentTestExpanderForValueToCoordinate) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const info = kTextureFormatInfo[t.params.format]; - await t.selectDeviceOrSkipTestCase(info.feature); + t.selectDeviceOrSkipTestCase(info.feature); }) .fn(async t => { const { valueToCoordinate, coordinateToTest, dimension, format, method } = t.params; diff --git a/src/webgpu/api/validation/query_set/create.spec.ts b/src/webgpu/api/validation/query_set/create.spec.ts index c2e7eb49c240..2c25a3561f52 100644 --- a/src/webgpu/api/validation/query_set/create.spec.ts +++ b/src/webgpu/api/validation/query_set/create.spec.ts @@ -22,8 +22,8 @@ Tests that create query set with the count for all query types: .beginSubcases() .combine('count', [0, kMaxQueryCount, kMaxQueryCount + 1]) ) - .beforeAllSubcases(async t => { - await t.selectDeviceForQueryTypeOrSkipTestCase(t.params.type); + .beforeAllSubcases(t => { + t.selectDeviceForQueryTypeOrSkipTestCase(t.params.type); }) .fn(async t => { const { type, count } = t.params; diff --git a/src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts b/src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts index 9fb377eb41c2..72e4fab113d8 100644 --- a/src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts +++ b/src/webgpu/api/validation/queue/copyToTexture/CopyExternalImageToTexture.spec.ts @@ -615,8 +615,8 @@ g.test('destination_texture,device_mismatch') 'Tests copyExternalImageToTexture cannot be called with a destination texture created from another device' ) .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; @@ -750,9 +750,9 @@ g.test('destination_texture,format') { width: 1, height: 1, depthOrArrayLayers: 1 }, ]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { format, copySize } = t.params; diff --git a/src/webgpu/api/validation/queue/destroyed/query_set.spec.ts b/src/webgpu/api/validation/queue/destroyed/query_set.spec.ts index c810073cdc82..87d85d10ee6b 100644 --- a/src/webgpu/api/validation/queue/destroyed/query_set.spec.ts +++ b/src/webgpu/api/validation/queue/destroyed/query_set.spec.ts @@ -32,7 +32,7 @@ Tests that use a destroyed query set in writeTimestamp on {non-pass, compute, re ` ) .params(u => u.beginSubcases().combine('querySetState', ['valid', 'destroyed'] as const)) - .beforeAllSubcases(async t => await t.selectDeviceOrSkipTestCase('timestamp-query')) + .beforeAllSubcases(t => t.selectDeviceOrSkipTestCase('timestamp-query')) .fn(async t => { const querySet = t.createQuerySetWithState(t.params.querySetState, { type: 'timestamp', diff --git a/src/webgpu/api/validation/queue/submit.spec.ts b/src/webgpu/api/validation/queue/submit.spec.ts index f2ffdd4cd7d0..74afc6cf31b4 100644 --- a/src/webgpu/api/validation/queue/submit.spec.ts +++ b/src/webgpu/api/validation/queue/submit.spec.ts @@ -24,8 +24,8 @@ g.test('command_buffer,device_mismatch') { cb0Mismatched: true, cb1Mismatched: false }, { cb0Mismatched: false, cb1Mismatched: true }, ]) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { cb0Mismatched, cb1Mismatched } = t.params; diff --git a/src/webgpu/api/validation/queue/writeBuffer.spec.ts b/src/webgpu/api/validation/queue/writeBuffer.spec.ts index 1d0e4108bb68..7ef735e506f3 100644 --- a/src/webgpu/api/validation/queue/writeBuffer.spec.ts +++ b/src/webgpu/api/validation/queue/writeBuffer.spec.ts @@ -176,8 +176,8 @@ Tests calling writeBuffer with the buffer missed COPY_DST usage. g.test('buffer,device_mismatch') .desc('Tests writeBuffer cannot be called with a buffer created from another device') .paramsSubcasesOnly(u => u.combine('mismatched', [true, false])) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const { mismatched } = t.params; diff --git a/src/webgpu/api/validation/render_pass_descriptor.spec.ts b/src/webgpu/api/validation/render_pass_descriptor.spec.ts index 76abab52c733..316faf2dd68a 100644 --- a/src/webgpu/api/validation/render_pass_descriptor.spec.ts +++ b/src/webgpu/api/validation/render_pass_descriptor.spec.ts @@ -607,8 +607,8 @@ g.test('depth_stencil_attachment') .combine('setDepthLoadStoreOp', [false, true]) .combine('setStencilLoadStoreOp', [false, true]) ) - .beforeAllSubcases(async t => { - await t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); + .beforeAllSubcases(t => { + t.selectDeviceForTextureFormatOrSkipTestCase(t.params.format); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.ts b/src/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.ts index a973311de7b3..851c4745afe6 100644 --- a/src/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.ts +++ b/src/webgpu/api/validation/resource_usages/texture/in_pass_encoder.spec.ts @@ -619,9 +619,9 @@ g.test('subresources_and_binding_types_combination_for_aspect') p.compute && (p.binding0InBundle || p.binding1InBundle || p.type1 === 'render-target') ) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { diff --git a/src/webgpu/api/validation/state/device_lost/destroy.spec.ts b/src/webgpu/api/validation/state/device_lost/destroy.spec.ts index 5c163c023d3c..d25c249d4370 100644 --- a/src/webgpu/api/validation/state/device_lost/destroy.spec.ts +++ b/src/webgpu/api/validation/state/device_lost/destroy.spec.ts @@ -194,9 +194,9 @@ Tests creating 2d compressed textures on destroyed device. Tests valid combinati ); }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { awaitLost, format, usageType, usageCopy } = t.params; @@ -269,9 +269,9 @@ Tests creating texture views on 2d compressed textures from destroyed device. Te ); }) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { awaitLost, format, usageType, usageCopy } = t.params; @@ -488,9 +488,9 @@ Tests creating query sets on destroyed device. ` ) .params(u => u.combine('type', kQueryTypes).beginSubcases().combine('awaitLost', [true, false])) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { type } = t.params; - await t.selectDeviceForQueryTypeOrSkipTestCase(type); + t.selectDeviceForQueryTypeOrSkipTestCase(type); }) .fn(async t => { const { awaitLost, type } = t.params; @@ -670,9 +670,9 @@ Tests encoding and finishing a writeTimestamp command on destroyed device. .combine('stage', kCommandValidationStages) .combine('awaitLost', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { type } = t.params; - await t.selectDeviceForQueryTypeOrSkipTestCase(type); + t.selectDeviceForQueryTypeOrSkipTestCase(type); }) .fn(async t => { const { type, stage, awaitLost } = t.params; @@ -856,9 +856,9 @@ Tests writeTexture on queue on destroyed device with compressed formats. .beginSubcases() .combine('awaitLost', [true, false]) ) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { format } = t.params; - await t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); + t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature); }) .fn(async t => { const { format, awaitLost } = t.params; diff --git a/src/webgpu/examples.spec.ts b/src/webgpu/examples.spec.ts index 7b506c8fbbb8..fb3bb6f1f9c5 100644 --- a/src/webgpu/examples.spec.ts +++ b/src/webgpu/examples.spec.ts @@ -228,11 +228,11 @@ g.test('gpu,with_texture_compression,bc') Tests that a BC format passes validation iff the feature is enabled.` ) .params(u => u.combine('textureCompressionBC', [false, true])) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { textureCompressionBC } = t.params; if (textureCompressionBC) { - await t.selectDeviceOrSkipTestCase('texture-compression-bc'); + t.selectDeviceOrSkipTestCase('texture-compression-bc'); } }) .fn(async t => { @@ -257,11 +257,11 @@ g.test('gpu,with_texture_compression,etc2') Tests that an ETC2 format passes validation iff the feature is enabled.` ) .params(u => u.combine('textureCompressionETC2', [false, true])) - .beforeAllSubcases(async t => { + .beforeAllSubcases(t => { const { textureCompressionETC2 } = t.params; if (textureCompressionETC2) { - await t.selectDeviceOrSkipTestCase('texture-compression-etc2' as GPUFeatureName); + t.selectDeviceOrSkipTestCase('texture-compression-etc2' as GPUFeatureName); } }) .fn(async t => { diff --git a/src/webgpu/gpu_test.ts b/src/webgpu/gpu_test.ts index 05d69b9c00bd..dc2bf2866034 100644 --- a/src/webgpu/gpu_test.ts +++ b/src/webgpu/gpu_test.ts @@ -64,117 +64,57 @@ export function initUncanonicalizedDeviceDescriptor( } export class GPUTestSubcaseBatchState extends SubcaseBatchState { - private provider: DeviceProvider | undefined; - /** Must not be replaced once acquired. */ - private acquiredDevice: GPUDevice | undefined; - - // Some tests(e.g. Device mismatched validation) require another GPUDevice - // different from the default GPUDevice of GPUTest. It is only used to - //create device mismatched objects. - private mismatchedProvider: DeviceProvider | undefined; - private mismatchedAcquiredDevice: GPUDevice | undefined; - - /** GPUDevice for the test to use. */ - get device(): GPUDevice { - assert( - this.provider !== undefined, - 'No provider available right now; did you "await" selectDeviceOrSkipTestCase?' - ); - if (!this.acquiredDevice) { - this.acquiredDevice = this.provider.acquire(); - } - return this.acquiredDevice; - } - - /** GPUDevice for tests requires another device from default one. - * e.g. creating objects required creating mismatched objects required - * by device mismatched validation tests. - */ - get mismatchedDevice(): GPUDevice { - assert( - this.mismatchedProvider !== undefined, - 'No provider available right now; did you "await" selectMismatchedDeviceOrSkipTestCase?' - ); - if (!this.mismatchedAcquiredDevice) { - this.mismatchedAcquiredDevice = this.mismatchedProvider.acquire(); - } - return this.mismatchedAcquiredDevice; - } + /** Provider for default device. */ + private provider: Promise | undefined; + /** Provider for mismatched device. */ + private mismatchedProvider: Promise | undefined; - /** - * Create other device different with current test device, which could be got by `.mismatchedDevice`. - * A `descriptor` may be undefined, which returns a `default` mismatched device. - * If the request descriptor or feature name can't be supported, throws an exception to skip the entire test case. - * - * MAINTENANCE_TODO: These device selection methods may not have to be async. - * They could be enqueued and then await'ed automatically after `beforeAllSubcases` - * runs. - */ - async selectMismatchedDeviceOrSkipTestCase(descriptor: DeviceSelectionDescriptor): Promise { - assert( - this.mismatchedProvider === undefined, - "Can't selectMismatchedDeviceOrSkipTestCase() multiple times" - ); - - this.mismatchedProvider = await mismatchedDevicePool.reserve( - initUncanonicalizedDeviceDescriptor(descriptor) - ); - - this.mismatchedAcquiredDevice = this.mismatchedProvider.acquire(); - } - - async init(): Promise { - await super.init(); - - this.provider = await devicePool.reserve(); + async postInit(): Promise { + // Skip all subcases if there's no device. + await this.acquireProvider(); } async finalize(): Promise { await super.finalize(); - if (this.provider) { - await devicePool.release(await this.provider); - } + // Ensure devicePool.release is called for both providers even if one rejects. + await Promise.all([ + this.provider?.then(x => devicePool.release(x)), + this.mismatchedProvider?.then(x => devicePool.release(x)), + ]); + } - if (this.mismatchedProvider) { - await devicePool.release(await this.mismatchedProvider); + /** @internal MAINTENANCE_TODO: Make this not visible to test code? */ + acquireProvider(): Promise { + if (this.provider === undefined) { + this.selectDeviceOrSkipTestCase(undefined); } + assert(this.provider !== undefined); + return this.provider; } /** - * When a GPUTest test accesses `.device` for the first time, a "default" GPUDevice - * (descriptor = `undefined`) is provided by default. - * However, some tests or cases need particular nonGuaranteedFeatures to be enabled. + * Some tests or cases need particular feature flags or limits to be enabled. * Call this function with a descriptor or feature name (or `undefined`) to select a - * GPUDevice with matching capabilities. + * GPUDevice with matching capabilities. If this isn't called, a default device is provided. * - * If the request descriptor can't be supported, throws an exception to skip the entire test case. + * If the request isn't supported, throws a SkipTestCase exception to skip the entire test case. */ - async selectDeviceOrSkipTestCase(descriptor: DeviceSelectionDescriptor): Promise { - if (descriptor === undefined) return; - - assert(this.provider !== undefined); - // Make sure the device isn't replaced after it's been retrieved once. - assert( - !this.acquiredDevice, - "Can't selectDeviceOrSkipTestCase() after the device has been used" - ); - - const oldProvider = this.provider; - this.provider = undefined; - await devicePool.release(oldProvider); - - this.provider = await devicePool.reserve(initUncanonicalizedDeviceDescriptor(descriptor)); - this.acquiredDevice = this.provider.acquire(); + selectDeviceOrSkipTestCase(descriptor: DeviceSelectionDescriptor): void { + assert(this.provider === undefined, "Can't selectDeviceOrSkipTestCase() multiple times"); + this.provider = devicePool.acquire(initUncanonicalizedDeviceDescriptor(descriptor)); + // Suppress uncaught promise rejection (we'll catch it later). + this.provider.catch(() => {}); } /** - * Create device with texture format(s) required feature(s). - * If the device creation fails, then skip the test for that format(s). + * Convenience function for {@link selectDeviceOrSkipTestCase}. + * Select a device with the features required by these texture format(s). + * If the device creation fails, then skip the test case. */ - async selectDeviceForTextureFormatOrSkipTestCase( + selectDeviceForTextureFormatOrSkipTestCase( formats: GPUTextureFormat | undefined | (GPUTextureFormat | undefined)[] - ): Promise { + ): void { if (!Array.isArray(formats)) { formats = [formats]; } @@ -185,32 +125,45 @@ export class GPUTestSubcaseBatchState extends SubcaseBatchState { } } - await this.selectDeviceOrSkipTestCase(Array.from(features)); + this.selectDeviceOrSkipTestCase(Array.from(features)); } /** - * Create device with query type(s) required feature(s). - * If the device creation fails, then skip the test for that type(s). + * Convenience function for {@link selectDeviceOrSkipTestCase}. + * Select a device with the features required by these query type(s). + * If the device creation fails, then skip the test case. */ - async selectDeviceForQueryTypeOrSkipTestCase( - types: GPUQueryType | GPUQueryType[] - ): Promise { + selectDeviceForQueryTypeOrSkipTestCase(types: GPUQueryType | GPUQueryType[]): void { if (!Array.isArray(types)) { types = [types]; } const features = types.map(t => kQueryTypeInfo[t].feature); - await this.selectDeviceOrSkipTestCase(features); + this.selectDeviceOrSkipTestCase(features); + } + + /** @internal MAINTENANCE_TODO: Make this not visible to test code? */ + acquireMismatchedProvider(): Promise | undefined { + return this.mismatchedProvider; } /** - * Expects that the device should be lost for a particular reason at the teardown of the test. + * Some tests need a second device which is different from the first. + * This requests a second device so it will be available during the test. If it is not called, + * no second device will be available. + * + * If the request isn't supported, throws a SkipTestCase exception to skip the entire test case. */ - expectDeviceLost(reason: GPUDeviceLostReason): void { + selectMismatchedDeviceOrSkipTestCase(descriptor: DeviceSelectionDescriptor): void { assert( - this.provider !== undefined, - 'No provider available right now; did you "await" selectDeviceOrSkipTestCase?' + this.mismatchedProvider === undefined, + "Can't selectMismatchedDeviceOrSkipTestCase() multiple times" ); - this.provider.expectDeviceLost(reason); + + this.mismatchedProvider = mismatchedDevicePool.acquire( + initUncanonicalizedDeviceDescriptor(descriptor) + ); + // Suppress uncaught promise rejection (we'll catch it later). + this.mismatchedProvider.catch(() => {}); } } @@ -222,17 +175,35 @@ export class GPUTest extends Fixture { return new GPUTestSubcaseBatchState(params); } - /** GPUDevice for the test to use. */ + // Should never be undefined in a test. If it is, init() must not have run/finished. + private provider: DeviceProvider | undefined; + private mismatchedProvider: DeviceProvider | undefined; + + async init() { + await super.init(); + + this.provider = await this.sharedState.acquireProvider(); + this.mismatchedProvider = await this.sharedState.acquireMismatchedProvider(); + } + + /** + * GPUDevice for the test to use. + */ get device(): GPUDevice { - return this.sharedState.device; + assert(this.provider !== undefined, 'internal error: GPUDevice missing?'); + return this.provider.device; } - /** GPUDevice for tests requires another device from default one. - * e.g. creating objects required creating mismatched objects required - * by device mismatched validation tests. + /** + * GPUDevice for tests requiring a second device different from the default one, + * e.g. for creating objects for by device_mismatch validation tests. */ get mismatchedDevice(): GPUDevice { - return this.sharedState.mismatchedDevice; + assert( + this.mismatchedProvider !== undefined, + 'selectMismatchedDeviceOrSkipTestCase was not called in beforeAllSubcases' + ); + return this.mismatchedProvider.device; } /** GPUQueue for the test to use. (Same as `t.device.queue`.) */ @@ -800,7 +771,8 @@ export class GPUTest extends Fixture { * Expects that the device should be lost for a particular reason at the teardown of the test. */ expectDeviceLost(reason: GPUDeviceLostReason): void { - this.sharedState.expectDeviceLost(reason); + assert(this.provider !== undefined, 'internal error: GPUDevice missing?'); + this.provider.expectDeviceLost(reason); } /** diff --git a/src/webgpu/util/device_pool.ts b/src/webgpu/util/device_pool.ts index 7ca883dfa6a7..f2b7005e832e 100644 --- a/src/webgpu/util/device_pool.ts +++ b/src/webgpu/util/device_pool.ts @@ -1,11 +1,16 @@ import { SkipTestCase } from '../../common/framework/fixture.js'; import { attemptGarbageCollection } from '../../common/util/collect_garbage.js'; import { getGPU } from '../../common/util/navigator_gpu.js'; -import { assert, raceWithRejectOnTimeout, assertReject } from '../../common/util/util.js'; +import { + assert, + raceWithRejectOnTimeout, + assertReject, + unreachable, +} from '../../common/util/util.js'; import { kLimitInfo, kLimits } from '../capability_info.js'; export interface DeviceProvider { - acquire(): GPUDevice; + readonly device: GPUDevice; expectDeviceLost(reason: GPUDeviceLostReason): void; } @@ -16,8 +21,8 @@ export class TestOOMedShouldAttemptGC extends Error {} export class DevicePool { private holders: 'uninitialized' | 'failed' | DescriptorToHolderMap = 'uninitialized'; - /** Request a device from the pool. */ - async reserve(descriptor?: UncanonicalizedDeviceDescriptor): Promise { + /** Acquire a device from the pool and begin the error scopes. */ + async acquire(descriptor?: UncanonicalizedDeviceDescriptor): Promise { let errorMessage = ''; if (this.holders === 'uninitialized') { this.holders = new DescriptorToHolderMap(); @@ -39,20 +44,22 @@ export class DevicePool { const holder = await this.holders.getOrCreate(descriptor); assert(holder.state === 'free', 'Device was in use on DevicePool.acquire'); - holder.state = 'reserved'; + holder.state = 'acquired'; + holder.beginTestScope(); return holder; } - // When a test is done using a device, it's released back into the pool. - // This waits for error scopes, checks their results, and checks for various error conditions. + /** + * End the error scopes and check for errors. + * Then, if the device seems reusable, release it back into the pool. Otherwise, drop it. + */ async release(holder: DeviceProvider): Promise { assert(this.holders instanceof DescriptorToHolderMap, 'DevicePool got into a bad state'); assert(holder instanceof DeviceHolder, 'DeviceProvider should always be a DeviceHolder'); - assert(holder.state !== 'free', 'trying to release a device while already released'); - + assert(holder.state === 'acquired', 'trying to release a device while already released'); try { - await holder.ensureRelease(); + await holder.endTestScope(); // (Hopefully if the device was lost, it has been reported by the time endErrorScopes() // has finished (or timed out). If not, it could cause a finite number of extra test @@ -90,8 +97,7 @@ export class DevicePool { throw ex; } } finally { - // Mark the holder as free. (This only has an effect if the pool still has the holder.) - // This could be done at the top but is done here to guard against async-races during release. + // Mark the holder as free so the device can be reused (if it's still in this.devices). holder.state = 'free'; } } @@ -106,13 +112,14 @@ class DescriptorToHolderMap { private holders: Map = new Map(); /** Deletes an item from the map by DeviceHolder value. */ - delete(device: DeviceHolder): void { + delete(holder: DeviceHolder): void { for (const [k, v] of this.holders) { - if (v === device) { + if (v === holder) { this.holders.delete(k); return; } } + unreachable("internal error: couldn't find DeviceHolder to delete"); } /** @@ -258,13 +265,12 @@ function supportsFeature( /** * DeviceHolder has three states: * - 'free': Free to be used for a new test. - * - 'reserved': Reserved by a running test, but has not had error scopes created yet. - * - 'acquired': Reserved by a running test, and has had error scopes created. + * - 'acquired': In use by a running test. */ -type DeviceHolderState = 'free' | 'reserved' | 'acquired'; +type DeviceHolderState = 'free' | 'acquired'; /** - * Holds a GPUDevice and tracks its state (free/reserved/acquired) and handles device loss. + * Holds a GPUDevice and tracks its state (free/acquired) and handles device loss. */ class DeviceHolder implements DeviceProvider { /** The device. Will be cleared during cleanup if there were unexpected errors. */ @@ -303,40 +309,37 @@ class DeviceHolder implements DeviceProvider { return this._device; } - acquire(): GPUDevice { - assert(this.state === 'reserved'); - this.state = 'acquired'; + /** Push error scopes that surround test execution. */ + beginTestScope(): void { + assert(this.state === 'acquired'); this.device.pushErrorScope('out-of-memory'); this.device.pushErrorScope('validation'); - return this.device; } + /** Mark the DeviceHolder as expecting a device loss when the test scope ends. */ expectDeviceLost(reason: GPUDeviceLostReason) { + assert(this.state === 'acquired'); this.expectedLostReason = reason; } - async ensureRelease(): Promise { - const kPopErrorScopeTimeoutMS = 5000; - - assert(this.state !== 'free'); - try { - if (this.state === 'acquired') { - // Time out if popErrorScope never completes. This could happen due to a browser bug - e.g., - // as of this writing, on Chrome GPU process crash, popErrorScope just hangs. - await raceWithRejectOnTimeout( - this.release(), - kPopErrorScopeTimeoutMS, - 'finalization popErrorScope timed out' - ); - } - } finally { - this.state = 'free'; - } + /** + * Attempt to end test scopes: Check that there are no extra error scopes, and that no + * otherwise-uncaptured errors occurred during the test. Time out if it takes too long. + */ + endTestScope(): Promise { + assert(this.state === 'acquired'); + const kTimeout = 5000; + + // Time out if attemptEndTestScope (popErrorScope or onSubmittedWorkDone) never completes. If + // this rejects, the device won't be reused, so it's OK that popErrorScope calls may not have + // finished. + // + // This could happen due to a browser bug - e.g., + // as of this writing, on Chrome GPU process crash, popErrorScope just hangs. + return raceWithRejectOnTimeout(this.attemptEndTestScope(), kTimeout, 'endTestScope timed out'); } - private async release(): Promise { - // End the whole-test error scopes. Check that there are no extra error scopes, and that no - // otherwise-uncaptured errors occurred during the test. + private async attemptEndTestScope(): Promise { let gpuValidationError: GPUValidationError | GPUOutOfMemoryError | null; let gpuOutOfMemoryError: GPUValidationError | GPUOutOfMemoryError | null; @@ -345,13 +348,12 @@ class DeviceHolder implements DeviceProvider { try { // May reject if the device was lost. - gpuValidationError = await this.device.popErrorScope(); - gpuOutOfMemoryError = await this.device.popErrorScope(); + [gpuValidationError, gpuOutOfMemoryError] = await Promise.all([ + this.device.popErrorScope(), + this.device.popErrorScope(), + ]); } catch (ex) { - assert( - this.lostInfo !== undefined, - 'popErrorScope failed; should only happen if device has been lost' - ); + assert(this.lostInfo !== undefined, 'popErrorScope failed; did beginTestScope get missed?'); throw ex; } diff --git a/src/webgpu/web_platform/copyToTexture/canvas.spec.ts b/src/webgpu/web_platform/copyToTexture/canvas.spec.ts index bd80d7ed6203..4ff8e0e353b0 100644 --- a/src/webgpu/web_platform/copyToTexture/canvas.spec.ts +++ b/src/webgpu/web_platform/copyToTexture/canvas.spec.ts @@ -625,8 +625,8 @@ g.test('copy_contents_from_gpu_context_canvas') .combine('width', [1, 2, 4, 15, 255, 256]) .combine('height', [1, 2, 4, 15, 255, 256]) ) - .beforeAllSubcases(async t => { - await t.selectMismatchedDeviceOrSkipTestCase(undefined); + .beforeAllSubcases(t => { + t.selectMismatchedDeviceOrSkipTestCase(undefined); }) .fn(async t => { const {