From 7ddcf7abbd107413106bf07aecaddd979e0e58d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Tue, 24 Jun 2025 14:29:13 +0200 Subject: [PATCH 1/3] Allow GPUTexture where GPUTextureView is used --- .../api/validation/createBindGroup.spec.ts | 22 +++++++++---------- .../render_pass_descriptor.spec.ts | 8 +++++-- .../validation/render_pass/resolve.spec.ts | 6 ++++- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/src/webgpu/api/validation/createBindGroup.spec.ts b/src/webgpu/api/validation/createBindGroup.spec.ts index 6ff09d8fb8df..3b64e187fdf7 100644 --- a/src/webgpu/api/validation/createBindGroup.spec.ts +++ b/src/webgpu/api/validation/createBindGroup.spec.ts @@ -610,9 +610,10 @@ g.test('texture,resource_state') .combine('state', kResourceStates) .combine('entry', sampledAndStorageBindingEntries(true, kTestFormat)) .combine('visibilityMask', [kAllShaderStages, GPUConst.ShaderStage.COMPUTE] as const) + .combine('bindTextureResource', [false, true] as const) ) .fn(t => { - const { state, entry, visibilityMask } = t.params; + const { state, entry, visibilityMask, bindTextureResource } = t.params; const info = texBindingTypeInfo(entry); const visibility = info.validStages & visibilityMask; @@ -640,20 +641,19 @@ g.test('texture,resource_state') sampleCount: entry.texture?.multisampled ? 4 : 1, }); - let textureView: GPUTextureView; - t.expectValidationError(() => { - textureView = texture.createView(); - }, state === 'invalid'); + let resource: GPUTexture | GPUTextureView; + if (bindTextureResource) { + resource = texture; + } else { + t.expectValidationError(() => { + resource = texture.createView(); + }, state === 'invalid'); + } t.expectValidationError(() => { t.device.createBindGroup({ layout: bgl, - entries: [ - { - binding: 0, - resource: textureView, - }, - ], + entries: [{ binding: 0, resource }], }); }, state === 'invalid'); }); diff --git a/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts b/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts index eea51d3c8f2a..a4e43b33a781 100644 --- a/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts +++ b/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts @@ -62,7 +62,8 @@ class F extends AllFeaturesMaxLimitsGPUTest { texture: GPUTexture, textureViewDescriptor?: GPUTextureViewDescriptor ): GPURenderPassColorAttachment { - const view = texture.createView(textureViewDescriptor); + const { bindTextureResource = false } = this.params as { bindTextureResource?: boolean }; + const view = bindTextureResource ? texture : texture.createView(textureViewDescriptor); return { view, @@ -76,7 +77,8 @@ class F extends AllFeaturesMaxLimitsGPUTest { texture: GPUTexture, textureViewDescriptor?: GPUTextureViewDescriptor ): GPURenderPassDepthStencilAttachment { - const view = texture.createView(textureViewDescriptor); + const { bindTextureResource = false } = this.params as { bindTextureResource?: boolean }; + const view = bindTextureResource ? texture : texture.createView(textureViewDescriptor); return { view, @@ -105,6 +107,7 @@ const kArrayLayerCount = 10; g.test('attachments,one_color_attachment') .desc(`Test that a render pass works with only one color attachment.`) + .paramsSubcasesOnly(u => u.combine('bindTextureResource', [false, true] as const)) .fn(t => { const colorTexture = t.createTestTexture({ format: 'rgba8unorm' }); const descriptor = { @@ -116,6 +119,7 @@ g.test('attachments,one_color_attachment') g.test('attachments,one_depth_stencil_attachment') .desc(`Test that a render pass works with only one depthStencil attachment.`) + .paramsSubcasesOnly(u => u.combine('bindTextureResource', [false, true] as const)) .fn(t => { const depthStencilTexture = t.createTestTexture({ format: 'depth24plus-stencil8' }); const descriptor = { diff --git a/src/webgpu/api/validation/render_pass/resolve.spec.ts b/src/webgpu/api/validation/render_pass/resolve.spec.ts index 50b405982878..1ef96643e374 100644 --- a/src/webgpu/api/validation/render_pass/resolve.spec.ts +++ b/src/webgpu/api/validation/render_pass/resolve.spec.ts @@ -32,8 +32,9 @@ Test various validation behaviors when a resolveTarget is provided. ` ) .paramsSimple([ - // control case should be valid + // control cases should be valid { _valid: true }, + { bindTextureResource: true, _valid: true }, // a single sampled resolve source should cause a validation error. { colorAttachmentSamples: 1, _valid: false }, // a multisampled resolve target should cause a validation error. @@ -78,6 +79,7 @@ Test various validation behaviors when a resolveTarget is provided. ] as const) .fn(t => { const { + bindTextureResource = false, colorAttachmentFormat = 'rgba8unorm', resolveTargetFormat = 'rgba8unorm', otherAttachmentFormat = 'rgba8unorm', @@ -139,6 +141,8 @@ Test various validation behaviors when a resolveTarget is provided. storeOp: 'discard', resolveTarget: resolveTargetInvalid ? vtu.getErrorTextureView(t) + : bindTextureResource + ? resolveTarget : resolveTarget.createView({ dimension: resolveTargetViewArrayLayerCount === 1 ? '2d' : '2d-array', mipLevelCount: resolveTargetViewMipCount, From 7e20a09a427031424d351fd86e4376c50012a599 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Wed, 25 Jun 2025 16:06:57 +0200 Subject: [PATCH 2/3] Fix nit --- .../render_pass_descriptor.spec.ts | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts b/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts index a4e43b33a781..725c19553456 100644 --- a/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts +++ b/src/webgpu/api/validation/render_pass/render_pass_descriptor.spec.ts @@ -60,9 +60,12 @@ class F extends AllFeaturesMaxLimitsGPUTest { getColorAttachment( texture: GPUTexture, - textureViewDescriptor?: GPUTextureViewDescriptor + options: { + textureViewDescriptor?: GPUTextureViewDescriptor; + bindTextureResource?: boolean; + } = {} ): GPURenderPassColorAttachment { - const { bindTextureResource = false } = this.params as { bindTextureResource?: boolean }; + const { textureViewDescriptor, bindTextureResource = false } = options; const view = bindTextureResource ? texture : texture.createView(textureViewDescriptor); return { @@ -75,9 +78,12 @@ class F extends AllFeaturesMaxLimitsGPUTest { getDepthStencilAttachment( texture: GPUTexture, - textureViewDescriptor?: GPUTextureViewDescriptor + options: { + textureViewDescriptor?: GPUTextureViewDescriptor; + bindTextureResource?: boolean; + } = {} ): GPURenderPassDepthStencilAttachment { - const { bindTextureResource = false } = this.params as { bindTextureResource?: boolean }; + const { textureViewDescriptor, bindTextureResource = false } = options; const view = bindTextureResource ? texture : texture.createView(textureViewDescriptor); return { @@ -354,14 +360,14 @@ g.test('color_attachments,depthSlice,bound_check') mipLevelCount: mipLevel + 1, }); - const viewDescriptor: GPUTextureViewDescriptor = { + const textureViewDescriptor: GPUTextureViewDescriptor = { baseMipLevel: mipLevel, mipLevelCount: 1, baseArrayLayer: 0, arrayLayerCount: 1, }; - const colorAttachment = t.getColorAttachment(texture, viewDescriptor); + const colorAttachment = t.getColorAttachment(texture, { textureViewDescriptor }); colorAttachment.depthSlice = depthSlice; const passDescriptor: GPURenderPassDescriptor = { @@ -446,7 +452,7 @@ g.test('color_attachments,depthSlice,overlaps,diff_miplevel') }; const texture = t.createTestTexture(texDescriptor); - const viewDescriptor: GPUTextureViewDescriptor = { + const textureViewDescriptor: GPUTextureViewDescriptor = { baseMipLevel: 0, mipLevelCount: 1, baseArrayLayer: 0, @@ -456,9 +462,9 @@ g.test('color_attachments,depthSlice,overlaps,diff_miplevel') const colorAttachments = []; for (let i = 0; i < mipLevelCount; i++) { if (!sameMipLevel) { - viewDescriptor.baseMipLevel = i; + textureViewDescriptor.baseMipLevel = i; } - const colorAttachment = t.getColorAttachment(texture, viewDescriptor); + const colorAttachment = t.getColorAttachment(texture, { textureViewDescriptor }); colorAttachment.depthSlice = 0; colorAttachments.push(colorAttachment); } @@ -609,7 +615,7 @@ g.test('attachments,layer_count') }; const descriptor: GPURenderPassDescriptor = { - colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)], + colorAttachments: [t.getColorAttachment(colorTexture, { textureViewDescriptor })], }; t.tryRenderPass(_success, descriptor); @@ -623,10 +629,9 @@ g.test('attachments,layer_count') const descriptor: GPURenderPassDescriptor = { colorAttachments: [], - depthStencilAttachment: t.getDepthStencilAttachment( - depthStencilTexture, - textureViewDescriptor - ), + depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture, { + textureViewDescriptor, + }), }; t.tryRenderPass(_success, descriptor); @@ -686,7 +691,7 @@ g.test('attachments,mip_level_count') }; const descriptor: GPURenderPassDescriptor = { - colorAttachments: [t.getColorAttachment(colorTexture, textureViewDescriptor)], + colorAttachments: [t.getColorAttachment(colorTexture, { textureViewDescriptor })], }; t.tryRenderPass(_success, descriptor); @@ -700,10 +705,9 @@ g.test('attachments,mip_level_count') const descriptor: GPURenderPassDescriptor = { colorAttachments: [], - depthStencilAttachment: t.getDepthStencilAttachment( - depthStencilTexture, - textureViewDescriptor - ), + depthStencilAttachment: t.getDepthStencilAttachment(depthStencilTexture, { + textureViewDescriptor, + }), }; t.tryRenderPass(_success, descriptor); From e1df39679aec9e07619f27052daf1a68bf6ec0a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fran=C3=A7ois=20Beaufort?= Date: Tue, 8 Jul 2025 08:35:13 +0200 Subject: [PATCH 3/3] Update webgpu types --- package-lock.json | 17 +++++++++-------- package.json | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4eecda06b3fb..9307fcc7d96d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "@types/w3c-image-capture": "^1.0.10", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", - "@webgpu/types": "^0.1.63", + "@webgpu/types": "^0.1.64", "ansi-colors": "4.1.3", "babel-plugin-add-header-comment": "^1.0.3", "babel-plugin-const-enum": "^1.2.0", @@ -1539,10 +1539,11 @@ "dev": true }, "node_modules/@webgpu/types": { - "version": "0.1.63", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.63.tgz", - "integrity": "sha512-s9Kuh0nE/2+nKrvmKNMB2fE5Zlr3DL2t3OFKM55v5jRcfCOxbkOHhQoshoFum5mmXIfEtRXtLCWmkeTJsVjE9w==", - "dev": true + "version": "0.1.64", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.64.tgz", + "integrity": "sha512-84kRIAGV46LJTlJZWxShiOrNL30A+9KokD7RB3dRCIqODFjodS5tCD5yyiZ8kIReGVZSDfA3XkkwyyOIF6K62A==", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/abbrev": { "version": "1.1.1", @@ -10076,9 +10077,9 @@ "dev": true }, "@webgpu/types": { - "version": "0.1.63", - "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.63.tgz", - "integrity": "sha512-s9Kuh0nE/2+nKrvmKNMB2fE5Zlr3DL2t3OFKM55v5jRcfCOxbkOHhQoshoFum5mmXIfEtRXtLCWmkeTJsVjE9w==", + "version": "0.1.64", + "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.64.tgz", + "integrity": "sha512-84kRIAGV46LJTlJZWxShiOrNL30A+9KokD7RB3dRCIqODFjodS5tCD5yyiZ8kIReGVZSDfA3XkkwyyOIF6K62A==", "dev": true }, "abbrev": { diff --git a/package.json b/package.json index 33eaf904509a..50c2f4b009a5 100644 --- a/package.json +++ b/package.json @@ -50,7 +50,7 @@ "@types/w3c-image-capture": "^1.0.10", "@typescript-eslint/eslint-plugin": "^6.9.1", "@typescript-eslint/parser": "^6.9.1", - "@webgpu/types": "^0.1.63", + "@webgpu/types": "^0.1.64", "ansi-colors": "4.1.3", "babel-plugin-add-header-comment": "^1.0.3", "babel-plugin-const-enum": "^1.2.0",