From 88932181827fc34ab7f74e8be820cac7a48f8062 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Wed, 20 May 2026 15:44:35 -0700 Subject: [PATCH 1/3] Test viewFormats with TRANSIENT_ATTACHMENT This should not be allowed. Issue: https://github.com/gpuweb/gpuweb/issues/6263 --- .../api/validation/createTexture.spec.ts | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/webgpu/api/validation/createTexture.spec.ts b/src/webgpu/api/validation/createTexture.spec.ts index 55ed721f22f0..247db7c024b4 100644 --- a/src/webgpu/api/validation/createTexture.spec.ts +++ b/src/webgpu/api/validation/createTexture.spec.ts @@ -1214,3 +1214,45 @@ g.test('viewFormats') }); }, !compatible); }); + +g.test('transient_viewFormats') + .desc(`Test that viewFormats is not allowed with TRANSIENT_ATTACHMENT textures.`) + .params(u => + u + // Just test rgba8unorm formats as this check doesn't care about what the format is. + .combineWithParams([ + { format: 'rgba8unorm', _otherFormat: 'rgba8unorm-srgb' }, + { format: 'rgba8unorm-srgb', _otherFormat: 'rgba8unorm' }, + ] as const) + .beginSubcases() + .expandWithParams(({ format, _otherFormat }) => [ + // Control cases + { useTransient: true, viewFormats: undefined }, + { useTransient: false, viewFormats: [format] }, + { useTransient: false, viewFormats: [_otherFormat] }, + // Invalid cases + { useTransient: true, viewFormats: [format] }, + { useTransient: true, viewFormats: [_otherFormat] }, + { useTransient: true, viewFormats: [format, _otherFormat] }, + ]) + ) + .fn(t => { + const { format, viewFormats, useTransient } = t.params; + t.skipIfTextureFormatNotSupported(format); + + const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format); + + const invalid = useTransient && viewFormats !== undefined; + t.expectValidationError(() => { + t.createTextureTracked({ + format, + size: [blockWidth, blockHeight], + usage: + GPUConst.TextureUsage.RENDER_ATTACHMENT | + (useTransient ? GPUConst.TextureUsage.TRANSIENT_ATTACHMENT : 0), + // Doesn't matter what formats we request, TRANSIENT_ATTACHMENT doesn't allow it. + // So we use [format] since that's otherwise ALWAYS valid regardless of format. + viewFormats, + }); + }, invalid); + }); From f40fc82cd93bb8233ec0c91ecf892f5eee4a0567 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Wed, 20 May 2026 22:39:42 -0700 Subject: [PATCH 2/3] also see what happens if we do try to create a view --- .../api/validation/createTexture.spec.ts | 29 ++++++++++++------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/src/webgpu/api/validation/createTexture.spec.ts b/src/webgpu/api/validation/createTexture.spec.ts index 247db7c024b4..1d911c0da436 100644 --- a/src/webgpu/api/validation/createTexture.spec.ts +++ b/src/webgpu/api/validation/createTexture.spec.ts @@ -1227,24 +1227,24 @@ g.test('transient_viewFormats') .beginSubcases() .expandWithParams(({ format, _otherFormat }) => [ // Control cases - { useTransient: true, viewFormats: undefined }, - { useTransient: false, viewFormats: [format] }, - { useTransient: false, viewFormats: [_otherFormat] }, + { useTransient: true, viewFormat: undefined }, + { useTransient: false, viewFormat: format }, + { useTransient: false, viewFormat: _otherFormat }, // Invalid cases - { useTransient: true, viewFormats: [format] }, - { useTransient: true, viewFormats: [_otherFormat] }, - { useTransient: true, viewFormats: [format, _otherFormat] }, + { useTransient: true, viewFormat: format }, + { useTransient: true, viewFormat: _otherFormat }, ]) ) .fn(t => { - const { format, viewFormats, useTransient } = t.params; + const { format, viewFormat, useTransient } = t.params; t.skipIfTextureFormatNotSupported(format); const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format); - const invalid = useTransient && viewFormats !== undefined; + const invalid = useTransient && viewFormat !== undefined; + let tex: GPUTexture; t.expectValidationError(() => { - t.createTextureTracked({ + tex = t.createTextureTracked({ format, size: [blockWidth, blockHeight], usage: @@ -1252,7 +1252,16 @@ g.test('transient_viewFormats') (useTransient ? GPUConst.TextureUsage.TRANSIENT_ATTACHMENT : 0), // Doesn't matter what formats we request, TRANSIENT_ATTACHMENT doesn't allow it. // So we use [format] since that's otherwise ALWAYS valid regardless of format. - viewFormats, + viewFormats: viewFormat ? [viewFormat] : undefined, }); }, invalid); + + if (invalid) { + // When we reach here the texture should be invalid, so creating a view should be invalid. + // But try it anyway just to see what happens - if the browser had a bug above, this could + // issue a bad command to the backend API. + t.expectValidationError(() => { + tex.createView({ format: viewFormat }); + }, true); + } }); From 870255013253f6b736c70ba4aa8ff1accd87109f Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Wed, 20 May 2026 22:50:56 -0700 Subject: [PATCH 3/3] fix for compat --- src/webgpu/api/validation/createTexture.spec.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/webgpu/api/validation/createTexture.spec.ts b/src/webgpu/api/validation/createTexture.spec.ts index 1d911c0da436..b1bf2cd9725d 100644 --- a/src/webgpu/api/validation/createTexture.spec.ts +++ b/src/webgpu/api/validation/createTexture.spec.ts @@ -1237,7 +1237,9 @@ g.test('transient_viewFormats') ) .fn(t => { const { format, viewFormat, useTransient } = t.params; - t.skipIfTextureFormatNotSupported(format); + if (viewFormat && !textureFormatsAreViewCompatible(t.device.features, format, viewFormat)) { + t.skip(`"${format}" and "${viewFormat}" are not view-compatible`); + } const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format);