From 1acb0a12e43e2e14f57279e071ac58e57d1f4f57 Mon Sep 17 00:00:00 2001 From: Kai Ninomiya Date: Mon, 5 Oct 2026 13:14:51 -0400 Subject: [PATCH] Add more tests for mixing up depth and color attachments No bug, I just wrote these to make sure our implementation was correct because something made me unsure. Also rename a helper function to be clearer. --- .../texture_component_swizzle.spec.ts | 4 +- .../render_pass_descriptor.spec.ts | 99 ++++++++++++++----- src/webgpu/format_info.ts | 2 +- src/webgpu/util/texture.ts | 4 +- 4 files changed, 79 insertions(+), 30 deletions(-) diff --git a/src/webgpu/api/operation/texture_view/texture_component_swizzle.spec.ts b/src/webgpu/api/operation/texture_view/texture_component_swizzle.spec.ts index d247572425c8..307c64049b74 100644 --- a/src/webgpu/api/operation/texture_view/texture_component_swizzle.spec.ts +++ b/src/webgpu/api/operation/texture_view/texture_component_swizzle.spec.ts @@ -26,7 +26,7 @@ import { isDepthTextureFormat, getBlockInfoForTextureFormat, isStencilTextureFormat, - isDepthStencilTextureFormat, + isDepthAndStencilTextureFormat, isTextureFormatPossiblyMultisampled, isTextureFormatUsableAsRenderAttachment, } from '../../../format_info.js'; @@ -312,7 +312,7 @@ g.test('read_swizzle') }; const { texels: srcTexelViews, texture } = await createTextureWithRandomDataAndGetTexelsForEachAspect(t, descriptor); - const aspectNdx = isDepthStencilTextureFormat(format) && aspect === 'stencil-only' ? 1 : 0; + const aspectNdx = isDepthAndStencilTextureFormat(format) && aspect === 'stencil-only' ? 1 : 0; const srcTexelView = srcTexelViews[aspectNdx]; const samples = []; 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 40166e96d481..55472c6b7afe 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 @@ -16,6 +16,8 @@ import { isTextureFormatColorRenderable, isDepthTextureFormat, isStencilTextureFormat, + isDepthAndStencilTextureFormat, + isDepthOrStencilTextureFormat, isTextureFormatResolvable, } from '../../../format_info.js'; import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js'; @@ -183,6 +185,40 @@ g.test('color_attachments,empty') }); }); +g.test('color_attachments,depth_stencil_format') + .desc( + ` + Test that texture views of depth and/or stencil format are invalid as color attachments in render passes: + - One control (color) case and all error (depth-and/or-stencil) cases. + ` + ) + .params(u => + u + .combine('format', ['rgba8unorm', ...kDepthStencilFormats] as const) + .beginSubcases() + .expand('aspect', p => + isDepthAndStencilTextureFormat(p.format) + ? (['all', 'depth-only', 'stencil-only'] as const) + : (['all'] as const) + ) + ) + .fn(t => { + const { format, aspect } = t.params; + t.skipIfTextureFormatNotSupported(format); + + const texture = t.createTestTexture({ format }); + const descriptor: GPURenderPassDescriptor = { + colorAttachments: [ + t.getColorAttachment(texture, { + textureViewDescriptor: { aspect }, + }), + ], + }; + + const isValid = isTextureFormatColorRenderable(t.device.features, format); + t.tryRenderPass(isValid, descriptor); + }); + g.test('color_attachments,limits,maxColorAttachments') .desc( ` @@ -541,31 +577,6 @@ g.test('attachments,same_size') } }); -g.test('attachments,color_depth_mismatch') - .desc(`Test that attachments match whether they are used for color or depth stencil.`) - .fn(t => { - const colorTexture = t.createTestTexture({ format: 'rgba8unorm' }); - const depthStencilTexture = t.createTestTexture({ format: 'depth24plus-stencil8' }); - - { - // Using depth-stencil for color - const descriptor: GPURenderPassDescriptor = { - colorAttachments: [t.getColorAttachment(depthStencilTexture)], - }; - - t.tryRenderPass(false, descriptor); - } - { - // Using color for depth-stencil - const descriptor: GPURenderPassDescriptor = { - colorAttachments: [], - depthStencilAttachment: t.getDepthStencilAttachment(colorTexture), - }; - - t.tryRenderPass(false, descriptor); - } - }); - g.test('attachments,layer_count') .desc( ` @@ -1023,6 +1034,44 @@ g.test('resolveTarget,different_size') } }); +g.test('depth_stencil_attachment,color_format') + .desc( + ` + Test that texture views of color formats are invalid as depth stencil attachments in render passes: + - One control (depth) case and a selection of error (color) cases. + ` + ) + .params(u => + u + .combine('format', [ + 'depth24plus-stencil8', + 'r8uint', + 'r8unorm', + 'rgba16float', + 'rgba8unorm', + ] as const) + .beginSubcases() + .expand('aspect', p => + isDepthAndStencilTextureFormat(p.format) + ? (['all', 'depth-only', 'stencil-only'] as const) + : (['all'] as const) + ) + ) + .fn(t => { + const { format } = t.params; + t.skipIfTextureFormatNotSupported(format); + t.skipIfTextureFormatNotUsableAsRenderAttachment(format); + + const texture = t.createTestTexture({ format }); + const descriptor: GPURenderPassDescriptor = { + colorAttachments: [], + depthStencilAttachment: t.getDepthStencilAttachment(texture), + }; + + const isValid = isDepthOrStencilTextureFormat(format); + t.tryRenderPass(isValid, descriptor); + }); + g.test('depth_stencil_attachment,sample_counts_mismatch') .desc( ` diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts index 8c09c3eb0f15..c36fa5a41dbc 100644 --- a/src/webgpu/format_info.ts +++ b/src/webgpu/format_info.ts @@ -2438,7 +2438,7 @@ export function isStencilTextureFormat(format: GPUTextureFormat) { return !!kTextureFormatInfo[format].stencil; } -export function isDepthStencilTextureFormat(format: GPUTextureFormat) { +export function isDepthAndStencilTextureFormat(format: GPUTextureFormat) { return isDepthTextureFormat(format) && isStencilTextureFormat(format); } diff --git a/src/webgpu/util/texture.ts b/src/webgpu/util/texture.ts index 1b18b3942d7b..29311e8bc0f2 100644 --- a/src/webgpu/util/texture.ts +++ b/src/webgpu/util/texture.ts @@ -2,7 +2,7 @@ import { assert, unreachable } from '../../common/util/util.js'; import { getBlockInfoForTextureFormat, isDepthOrStencilTextureFormat, - isDepthStencilTextureFormat, + isDepthAndStencilTextureFormat, isDepthTextureFormat, isSintOrUintFormat, isStencilTextureFormat, @@ -752,7 +752,7 @@ export function createTextureFromTexelViews( // Note: At the time of this writing there is no such thing as a depth-stencil TexelView // so we couldn't have passed in data for "all" aspects. This seems like a code smell issue // but it's a big change to fix. - const aspect = isDepthStencilTextureFormat(textureFormat) + const aspect = isDepthAndStencilTextureFormat(textureFormat) ? isSintOrUintFormat(viewsFormat) ? 'stencil-only' : 'depth-only'