diff --git a/src/webgpu/api/operation/resource_init/buffer.spec.ts b/src/webgpu/api/operation/resource_init/buffer.spec.ts index d6a6f22838a0..e410ccacf9fa 100644 --- a/src/webgpu/api/operation/resource_init/buffer.spec.ts +++ b/src/webgpu/api/operation/resource_init/buffer.spec.ts @@ -1,7 +1,7 @@ import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { unreachable } from '../../../../common/util/util.js'; import { GPUConst } from '../../../constants.js'; -import { GPUTest } from '../../../gpu_test.js'; +import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js'; import { getTextureCopyLayout } from '../../../util/texture/layout.js'; import { PerTexelComponent } from '../../../util/texture/texel_data.js'; @@ -21,7 +21,7 @@ const kBufferUsagesForMappedAtCreationTests = [ GPUConst.BufferUsage.COPY_SRC, ]; -class F extends GPUTest { +class F extends AllFeaturesMaxLimitsGPUTest { GetBufferUsageFromMapMode(mapMode: GPUMapModeFlags): number { switch (mapMode) { case GPUMapMode.READ: diff --git a/src/webgpu/api/operation/resource_init/check_texture/by_copy.ts b/src/webgpu/api/operation/resource_init/check_texture/by_copy.ts index 8562acc0bac2..7ad6e7ef5f9c 100644 --- a/src/webgpu/api/operation/resource_init/check_texture/by_copy.ts +++ b/src/webgpu/api/operation/resource_init/check_texture/by_copy.ts @@ -1,5 +1,4 @@ -import { assert } from '../../../../../common/util/util.js'; -import { kTextureFormatInfo, EncodableTextureFormat } from '../../../../format_info.js'; +import { EncodableTextureFormat } from '../../../../format_info.js'; import { virtualMipSize } from '../../../../util/texture/base.js'; import { CheckContents } from './texture_zero_init_test.js'; @@ -12,7 +11,6 @@ export const checkContentsByBufferCopy: CheckContents = ( subresourceRange ) => { for (const { level: mipLevel, layer } of subresourceRange.each()) { - assert(params.format in kTextureFormatInfo); const format = params.format as EncodableTextureFormat; t.expectSingleColor(texture, format, { @@ -33,7 +31,6 @@ export const checkContentsByTextureCopy: CheckContents = ( subresourceRange ) => { for (const { level, layer } of subresourceRange.each()) { - assert(params.format in kTextureFormatInfo); const format = params.format as EncodableTextureFormat; const [width, height, depth] = virtualMipSize( diff --git a/src/webgpu/api/operation/resource_init/check_texture/by_ds_test.ts b/src/webgpu/api/operation/resource_init/check_texture/by_ds_test.ts index 4b83e12c8b0b..e0440090e111 100644 --- a/src/webgpu/api/operation/resource_init/check_texture/by_ds_test.ts +++ b/src/webgpu/api/operation/resource_init/check_texture/by_ds_test.ts @@ -1,5 +1,5 @@ import { assert } from '../../../../../common/util/util.js'; -import { kTextureFormatInfo } from '../../../../format_info.js'; +import { isDepthTextureFormat, isStencilTextureFormat } from '../../../../format_info.js'; import { GPUTest } from '../../../../gpu_test.js'; import { virtualMipSize } from '../../../../util/texture/base.js'; @@ -106,8 +106,6 @@ const checkContents: (type: 'depth' | 'stencil', ...args: Parameters { - const formatInfo = kTextureFormatInfo[params.format]; - assert(params.dimension === '2d'); for (const viewDescriptor of t.generateTextureViewDescriptorsForRendering( 'all', @@ -153,10 +151,10 @@ const checkContents: (type: 'depth' | 'stencil', ...args: Parameters { - assert(params.format in kTextureFormatInfo); const format = params.format as EncodableTextureFormat; const rep = kTexelRepresentationInfo[format]; diff --git a/src/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.ts b/src/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.ts index cc959d4209a5..7f81f30281b8 100644 --- a/src/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.ts +++ b/src/webgpu/api/operation/resource_init/check_texture/texture_zero_init_test.ts @@ -7,13 +7,22 @@ import { assert, unreachable } from '../../../../../common/util/util.js'; import { kTextureAspects, kTextureDimensions } from '../../../../capability_info.js'; import { GPUConst } from '../../../../constants.js'; import { - kTextureFormatInfo, kUncompressedTextureFormats, textureDimensionAndFormatCompatible, UncompressedTextureFormat, EncodableTextureFormat, + isColorTextureFormat, + isDepthTextureFormat, + isStencilTextureFormat, + isDepthOrStencilTextureFormat, + isTextureFormatPossiblyUsableAsRenderAttachment, + isTextureFormatPossiblyStorageReadable, + isTextureFormatPossiblyMultisampled, + canCopyAllAspectsOfTextureFormat, + isTextureFormatColorRenderable, + isTextureFormatPossiblyUsableAsColorRenderAttachment, } from '../../../../format_info.js'; -import { GPUTest, GPUTestSubcaseBatchState } from '../../../../gpu_test.js'; +import { AllFeaturesMaxLimitsGPUTest, GPUTestSubcaseBatchState } from '../../../../gpu_test.js'; import { virtualMipSize } from '../../../../util/texture/base.js'; import { createTextureUploadBuffer } from '../../../../util/texture/layout.js'; import { BeginEndRange, SubresourceRange } from '../../../../util/texture/subresource.js'; @@ -115,14 +124,6 @@ const initializedStateAsStencil = { [InitializedState.Canary]: 42, }; -function allAspectsCopyDst(info: (typeof kTextureFormatInfo)[UncompressedTextureFormat]) { - return ( - (!info.color || info.color.copyDst) && - (!info.depth || info.depth.copyDst) && - (!info.stencil || info.stencil.copyDst) - ); -} - export function getRequiredTextureUsage( format: UncompressedTextureFormat, sampleCount: number, @@ -167,18 +168,22 @@ export function getRequiredTextureUsage( usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; } - const info = kTextureFormatInfo[format]; - if (!allAspectsCopyDst(info)) { + if (!canCopyAllAspectsOfTextureFormat(format)) { // Copies are not possible. We need OutputAttachment to initialize // canary data. - if (info.color) assert(!!info.colorRender, 'not implemented for non-renderable color'); + if (isColorTextureFormat(format)) { + assert( + isTextureFormatPossiblyUsableAsColorRenderAttachment(format), + 'not implemented for non-renderable color' + ); + } usage |= GPUConst.TextureUsage.RENDER_ATTACHMENT; } return usage; } -export class TextureZeroInitTest extends GPUTest { +export class TextureZeroInitTest extends AllFeaturesMaxLimitsGPUTest { readonly stateToTexelComponents: { [k in InitializedState]: PerTexelComponent }; private p: TextureZeroParams; @@ -302,7 +307,7 @@ export class TextureZeroInitTest extends GPUTest { 'all', subresourceRange )) { - if (kTextureFormatInfo[this.p.format].color) { + if (isColorTextureFormat(this.p.format)) { commandEncoder .beginRenderPass({ colorAttachments: [ @@ -319,12 +324,12 @@ export class TextureZeroInitTest extends GPUTest { const depthStencilAttachment: GPURenderPassDepthStencilAttachment = { view: texture.createView(viewDescriptor), }; - if (kTextureFormatInfo[this.p.format].depth) { + if (isDepthTextureFormat(this.p.format)) { depthStencilAttachment.depthClearValue = initializedStateAsDepth[state]; depthStencilAttachment.depthLoadOp = 'clear'; depthStencilAttachment.depthStoreOp = 'store'; } - if (kTextureFormatInfo[this.p.format].stencil) { + if (isStencilTextureFormat(this.p.format)) { depthStencilAttachment.stencilClearValue = initializedStateAsStencil[state]; depthStencilAttachment.stencilLoadOp = 'clear'; depthStencilAttachment.stencilStoreOp = 'store'; @@ -347,7 +352,6 @@ export class TextureZeroInitTest extends GPUTest { state: InitializedState, subresourceRange: SubresourceRange ): void { - assert(this.p.format in kTextureFormatInfo); const format = this.p.format as EncodableTextureFormat; const firstSubresource = subresourceRange.each().next().value; @@ -394,11 +398,15 @@ export class TextureZeroInitTest extends GPUTest { state: InitializedState, subresourceRange: SubresourceRange ): void { - const info = kTextureFormatInfo[this.p.format]; - if (this.p.sampleCount > 1 || !allAspectsCopyDst(info)) { + if (this.p.sampleCount > 1 || !canCopyAllAspectsOfTextureFormat(this.p.format)) { // Copies to multisampled textures not yet specified. // Use a storeOp for now. - if (info.color) assert(!!info.colorRender, 'not implemented for non-renderable color'); + if (isColorTextureFormat(this.p.format)) { + assert( + isTextureFormatColorRenderable(this.device, this.p.format), + 'not implemented for non-renderable color' + ); + } this.initializeWithStoreOp(state, texture, subresourceRange); } else { this.initializeWithCopy(texture, state, subresourceRange); @@ -410,7 +418,7 @@ export class TextureZeroInitTest extends GPUTest { commandEncoder.pushDebugGroup('discardTexture'); for (const desc of this.generateTextureViewDescriptorsForRendering('all', subresourceRange)) { - if (kTextureFormatInfo[this.p.format].color) { + if (isColorTextureFormat(this.p.format)) { commandEncoder .beginRenderPass({ colorAttachments: [ @@ -426,11 +434,11 @@ export class TextureZeroInitTest extends GPUTest { const depthStencilAttachment: GPURenderPassDepthStencilAttachment = { view: texture.createView(desc), }; - if (kTextureFormatInfo[this.p.format].depth) { + if (isDepthTextureFormat(this.p.format)) { depthStencilAttachment.depthLoadOp = 'load'; depthStencilAttachment.depthStoreOp = 'discard'; } - if (kTextureFormatInfo[this.p.format].stencil) { + if (isStencilTextureFormat(this.p.format)) { depthStencilAttachment.stencilLoadOp = 'load'; depthStencilAttachment.stencilStoreOp = 'discard'; } @@ -446,6 +454,19 @@ export class TextureZeroInitTest extends GPUTest { commandEncoder.popDebugGroup(); this.queue.submit([commandEncoder.finish()]); } + + skipIfTextureFormatNotSupportedForTest(params: TextureZeroParams) { + const { format, sampleCount, uninitializeMethod, readMethod } = params; + this.skipIfTextureFormatNotSupported(format); + + const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); + + this.skipIfTextureFormatDoesNotSupportUsage(usage, format); + + if (sampleCount > 1) { + this.skipIfTextureFormatNotMultisampled(format); + } + } } export const kTestParams = kUnitCaseParamsBuilder @@ -463,16 +484,18 @@ export const kTestParams = kUnitCaseParamsBuilder .beginSubcases() .combine('aspect', kTextureAspects) .unless(({ readMethod, format, aspect }) => { - const info = kTextureFormatInfo[format]; + const hasColor = isColorTextureFormat(format); + const hasDepth = isDepthTextureFormat(format); + const hasStencil = isStencilTextureFormat(format); return ( - (readMethod === ReadMethod.DepthTest && (!info.depth || aspect === 'stencil-only')) || - (readMethod === ReadMethod.StencilTest && (!info.stencil || aspect === 'depth-only')) || - (readMethod === ReadMethod.ColorBlending && !info.color) || + (readMethod === ReadMethod.DepthTest && (!hasDepth || aspect === 'stencil-only')) || + (readMethod === ReadMethod.StencilTest && (!hasStencil || aspect === 'depth-only')) || + (readMethod === ReadMethod.ColorBlending && !hasColor) || // [1]: Test with depth/stencil sampling - (readMethod === ReadMethod.Sample && (!!info.depth || !!info.stencil)) || - (aspect === 'depth-only' && !info.depth) || - (aspect === 'stencil-only' && !info.stencil) || - (aspect === 'all' && !!info.depth && !!info.stencil) || + (readMethod === ReadMethod.Sample && (hasDepth || hasStencil)) || + (aspect === 'depth-only' && !hasDepth) || + (aspect === 'stencil-only' && !hasStencil) || + (aspect === 'all' && !!hasDepth && !!hasStencil) || // Cannot copy from a packed depth format. // [2]: Test copying out of the stencil aspect. ((readMethod === ReadMethod.CopyToBuffer || readMethod === ReadMethod.CopyToTexture) && @@ -493,12 +516,10 @@ export const kTestParams = kUnitCaseParamsBuilder .unless(({ sampleCount, mipLevelCount }) => sampleCount > 1 && mipLevelCount > 1) .combine('uninitializeMethod', kUninitializeMethods) .unless(({ dimension, readMethod, uninitializeMethod, format, sampleCount }) => { - const formatInfo = kTextureFormatInfo[format]; return ( dimension !== '2d' && (sampleCount > 1 || - !!formatInfo.depth || - !!formatInfo.stencil || + isDepthOrStencilTextureFormat(format) || readMethod === ReadMethod.DepthTest || readMethod === ReadMethod.StencilTest || readMethod === ReadMethod.ColorBlending || @@ -521,14 +542,13 @@ export const kTestParams = kUnitCaseParamsBuilder .unless(({ sampleCount, layerCount }) => sampleCount > 1 && layerCount > 1) .unless(({ format, sampleCount, uninitializeMethod, readMethod }) => { const usage = getRequiredTextureUsage(format, sampleCount, uninitializeMethod, readMethod); - const info = kTextureFormatInfo[format]; return ( ((usage & GPUConst.TextureUsage.RENDER_ATTACHMENT) !== 0 && - info.color && - !info.colorRender) || - ((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && !info.color?.storage) || - (sampleCount > 1 && !info.multisample) + !isTextureFormatPossiblyUsableAsRenderAttachment(format)) || + ((usage & GPUConst.TextureUsage.STORAGE_BINDING) !== 0 && + !isTextureFormatPossiblyStorageReadable(format)) || + (sampleCount > 1 && !isTextureFormatPossiblyMultisampled(format)) ); }) .combine('nonPowerOfTwo', [false, true]) 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 4669ffdef9a8..8eb0f06411b8 100644 --- a/src/webgpu/api/operation/resource_init/texture_zero.spec.ts +++ b/src/webgpu/api/operation/resource_init/texture_zero.spec.ts @@ -9,7 +9,6 @@ TODO: import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { unreachable } from '../../../../common/util/util.js'; -import { isMultisampledTextureFormatDeprecated, kTextureFormatInfo } from '../../../format_info.js'; import { checkContentsByBufferCopy, checkContentsByTextureCopy } from './check_texture/by_copy.js'; import { @@ -41,15 +40,8 @@ export const g = makeTestGroup(TextureZeroInitTest); g.test('uninitialized_texture_is_zero') .params(kTestParams) - .beforeAllSubcases(t => { - t.skipIfTextureFormatNotSupportedDeprecated(t.params.format); - t.selectDeviceOrSkipTestCase(kTextureFormatInfo[t.params.format].feature); - }) .fn(t => { - t.skipIf( - t.params.sampleCount > 1 && - !isMultisampledTextureFormatDeprecated(t.params.format, t.isCompatibility) - ); + t.skipIfTextureFormatNotSupportedForTest(t.params); const usage = getRequiredTextureUsage( t.params.format, diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts index acb06a992fe5..087e2dc837d3 100644 --- a/src/webgpu/format_info.ts +++ b/src/webgpu/format_info.ts @@ -1894,10 +1894,23 @@ export function filterFormatsByFeature( return formats.filter(f => f === undefined || kTextureFormatInfo[f].feature === feature); } +export function canCopyAllAspectsOfTextureFormat(format: GPUTextureFormat) { + const info = kTextureFormatInfo[format]; + return ( + (!info.color || info.color.copyDst) && + (!info.depth || info.depth.copyDst) && + (!info.stencil || info.stencil.copyDst) + ); +} + export function isCompressedTextureFormat(format: GPUTextureFormat) { return format in kCompressedTextureFormatInfo; } +export function isColorTextureFormat(format: GPUTextureFormat) { + return !!kTextureFormatInfo[format].color; +} + export function isDepthTextureFormat(format: GPUTextureFormat) { return !!kTextureFormatInfo[format].depth; }