diff --git a/src/unittests/texture_ok.spec.ts b/src/unittests/texture_ok.spec.ts index f1e6971a74a0..c126832b8dc2 100644 --- a/src/unittests/texture_ok.spec.ts +++ b/src/unittests/texture_ok.spec.ts @@ -4,7 +4,6 @@ Test for texture_ok utils. import { makeTestGroup } from '../common/framework/test_group.js'; import { typedArrayFromParam, typedArrayParam } from '../common/util/util.js'; -import { RegularTextureFormat } from '../webgpu/format_info.js'; import { TexelView } from '../webgpu/util/texture/texel_view.js'; import { findFailedPixels } from '../webgpu/util/texture/texture_ok.js'; @@ -30,103 +29,103 @@ g.test('findFailedPixels') u.combineWithParams([ // Sanity Check { - format: 'rgba8unorm' as RegularTextureFormat, + format: 'rgba8unorm', actual: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), expected: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), isSame: true, }, // Slightly different values { - format: 'rgba8unorm' as RegularTextureFormat, + format: 'rgba8unorm', actual: typedArrayParam('Uint8Array', [0x00, 0x40, 0x80, 0xff]), expected: typedArrayParam('Uint8Array', [0x00, 0x40, 0x81, 0xff]), isSame: false, }, // Different representations of the same value { - format: 'rgb9e5ufloat' as RegularTextureFormat, + format: 'rgb9e5ufloat', actual: typedArrayParam('Uint8Array', [0x78, 0x56, 0x34, 0x12]), expected: typedArrayParam('Uint8Array', [0xf0, 0xac, 0x68, 0x0c]), isSame: true, }, // Slightly different values { - format: 'rgb9e5ufloat' as RegularTextureFormat, + format: 'rgb9e5ufloat', actual: typedArrayParam('Uint8Array', [0x78, 0x56, 0x34, 0x12]), expected: typedArrayParam('Uint8Array', [0xf1, 0xac, 0x68, 0x0c]), isSame: false, }, // Test NaN === NaN { - format: 'r32float' as RegularTextureFormat, + format: 'r32float', actual: typedArrayParam('Float32Array', [parseFloat('abc')]), expected: typedArrayParam('Float32Array', [parseFloat('def')]), isSame: true, }, // Sanity Check { - format: 'r32float' as RegularTextureFormat, + format: 'r32float', actual: typedArrayParam('Float32Array', [1.23]), expected: typedArrayParam('Float32Array', [1.23]), isSame: true, }, // Slightly different values. { - format: 'r32float' as RegularTextureFormat, + format: 'r32float', actual: typedArrayParam('Uint32Array', [0x3f9d70a4]), expected: typedArrayParam('Uint32Array', [0x3f9d70a5]), isSame: false, }, // Slightly different { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0x3ce]), expected: typedArrayParam('Uint32Array', [0x3cf]), isSame: false, }, // Positive.Infinity === Positive.Infinity (red) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b11111000000]), expected: typedArrayParam('Uint32Array', [0b11111000000]), isSame: true, }, // Positive.Infinity === Positive.Infinity (green) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b11111000000_00000000000]), expected: typedArrayParam('Uint32Array', [0b11111000000_00000000000]), isSame: true, }, // Positive.Infinity === Positive.Infinity (blue) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b1111100000_00000000000_00000000000]), expected: typedArrayParam('Uint32Array', [0b1111100000_00000000000_00000000000]), isSame: true, }, // NaN === NaN (red) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b11111000001]), expected: typedArrayParam('Uint32Array', [0b11111000010]), isSame: true, }, // NaN === NaN (green) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b11111000100_00000000000]), expected: typedArrayParam('Uint32Array', [0b11111001000_00000000000]), isSame: true, }, // NaN === NaN (blue) { - format: 'rg11b10ufloat' as RegularTextureFormat, + format: 'rg11b10ufloat', actual: typedArrayParam('Uint32Array', [0b1111110000_00000000000_00000000000]), expected: typedArrayParam('Uint32Array', [0b1111101000_00000000000_00000000000]), isSame: true, }, - ]) + ] as const) ) .fn(t => { const { format, actual, expected, isSame } = t.params; diff --git a/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts b/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts index f08b7fd5b42e..edf08c3840a1 100644 --- a/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts +++ b/src/webgpu/api/operation/command_buffer/copyTextureToTexture.spec.ts @@ -17,9 +17,9 @@ import { DepthStencilFormat, ColorTextureFormat, isCompressedTextureFormat, - isEncodableTextureformat, viewCompatible, - EncodableTextureFormat, + RegularTextureFormat, + isRegularTextureFormat, } from '../../../format_info.js'; import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; import { makeBufferWithContents } from '../../../util/buffer.js'; @@ -346,21 +346,21 @@ class F extends TextureTestMixin(GPUTest) { return; } - assert(isEncodableTextureformat(dstFormat)); - const encodableDstFormat = dstFormat as EncodableTextureFormat; + assert(isRegularTextureFormat(dstFormat)); + const regularDstFormat = dstFormat as RegularTextureFormat; // Verify the content of the whole subresource of dstTexture at dstCopyLevel (in dstBuffer) is expected. const checkByTextureFormat = (actual: Uint8Array) => { const zero = { x: 0, y: 0, z: 0 }; - const actTexelView = TexelView.fromTextureDataByReference(encodableDstFormat, actual, { + const actTexelView = TexelView.fromTextureDataByReference(regularDstFormat, actual, { bytesPerRow: bytesInRow, rowsPerImage: dstBlockRowsPerImage, subrectOrigin: zero, subrectSize: dstTextureSizeAtLevel, }); const expTexelView = TexelView.fromTextureDataByReference( - encodableDstFormat, + regularDstFormat, expectedUint8DataWithPadding, { bytesPerRow: bytesInRow, @@ -371,7 +371,7 @@ class F extends TextureTestMixin(GPUTest) { ); const failedPixelsMessage = findFailedPixels( - encodableDstFormat, + regularDstFormat, zero, dstTextureSizeAtLevel, { actTexelView, expTexelView }, diff --git a/src/webgpu/api/operation/rendering/color_target_state.spec.ts b/src/webgpu/api/operation/rendering/color_target_state.spec.ts index 1290c6bc99f6..0617b8f3592d 100644 --- a/src/webgpu/api/operation/rendering/color_target_state.spec.ts +++ b/src/webgpu/api/operation/rendering/color_target_state.spec.ts @@ -11,7 +11,7 @@ import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { assert, TypedArrayBufferView, unreachable } from '../../../../common/util/util.js'; import { kBlendFactors, kBlendOperations } from '../../../capability_info.js'; import { GPUConst } from '../../../constants.js'; -import { kEncodableTextureFormats, kTextureFormatInfo } from '../../../format_info.js'; +import { kRegularTextureFormats, kTextureFormatInfo } from '../../../format_info.js'; import { GPUTest, TextureTestMixin } from '../../../gpu_test.js'; import { clamp } from '../../../util/math.js'; import { TexelView } from '../../../util/texture/texel_view.js'; @@ -318,9 +318,9 @@ struct Uniform { ); }); -const kBlendableFormats = kEncodableTextureFormats.filter(f => { +const kBlendableFormats = kRegularTextureFormats.filter(f => { const info = kTextureFormatInfo[f]; - return info.renderable && info.sampleType === 'float'; + return info.colorRender && info.color.type === 'float'; }); g.test('blending,formats') diff --git a/src/webgpu/api/validation/image_copy/image_copy.ts b/src/webgpu/api/validation/image_copy/image_copy.ts index 686a5ee1cf96..0290046675ed 100644 --- a/src/webgpu/api/validation/image_copy/image_copy.ts +++ b/src/webgpu/api/validation/image_copy/image_copy.ts @@ -255,9 +255,9 @@ export function formatCopyableWithMethod({ format, method }: WithFormatAndMethod return supportedAspects.length > 0; } if (method === 'CopyT2B') { - return info.copySrc; + return info.color.copySrc; } else { - return info.copyDst; + return info.color.copyDst; } } diff --git a/src/webgpu/api/validation/render_pipeline/common.ts b/src/webgpu/api/validation/render_pipeline/common.ts index 93b0932042f4..e0316a5517e4 100644 --- a/src/webgpu/api/validation/render_pipeline/common.ts +++ b/src/webgpu/api/validation/render_pipeline/common.ts @@ -1,4 +1,4 @@ -import { kTextureFormatInfo } from '../../../format_info.js'; +import { ColorTextureFormat, kTextureFormatInfo } from '../../../format_info.js'; import { getFragmentShaderCodeWithOutput, getPlainTypeInfo, @@ -6,12 +6,14 @@ import { } from '../../../util/shader.js'; import { ValidationTest } from '../validation_test.js'; +type ColorTargetState = GPUColorTargetState & { format: ColorTextureFormat }; + const values = [0, 1, 0, 1]; export class CreateRenderPipelineValidationTest extends ValidationTest { getDescriptor( options: { primitive?: GPUPrimitiveState; - targets?: GPUColorTargetState[]; + targets?: ColorTargetState[]; multisample?: GPUMultisampleState; depthStencil?: GPUDepthStencilState; fragmentShaderCode?: string; @@ -19,17 +21,16 @@ export class CreateRenderPipelineValidationTest extends ValidationTest { fragmentConstants?: Record; } = {} ): GPURenderPipelineDescriptor { - const defaultTargets: GPUColorTargetState[] = [{ format: 'rgba8unorm' }]; const { primitive = {}, - targets = defaultTargets, + targets = [{ format: 'rgba8unorm' }] as const, multisample = {}, depthStencil, fragmentShaderCode = getFragmentShaderCodeWithOutput([ { values, plainType: getPlainTypeInfo( - kTextureFormatInfo[targets[0] ? targets[0].format : 'rgba8unorm'].sampleType + kTextureFormatInfo[targets[0] ? targets[0].format : 'rgba8unorm'].color.type ), componentCount: 4, }, diff --git a/src/webgpu/api/validation/render_pipeline/fragment_state.spec.ts b/src/webgpu/api/validation/render_pipeline/fragment_state.spec.ts index 3f2f02788529..c01c2ba9efdd 100644 --- a/src/webgpu/api/validation/render_pipeline/fragment_state.spec.ts +++ b/src/webgpu/api/validation/render_pipeline/fragment_state.spec.ts @@ -211,24 +211,12 @@ g.test('limits,maxColorAttachmentBytesPerSample,unaligned') // become 4 and 4+4+8+16+1 > 32. Re-ordering this so the R8Unorm's are at the end, however // is allowed: 4+8+16+1+1 < 32. { - formats: [ - 'r8unorm', - 'r32float', - 'rgba8unorm', - 'rgba32float', - 'r8unorm', - ] as GPUTextureFormat[], + formats: ['r8unorm', 'r32float', 'rgba8unorm', 'rgba32float', 'r8unorm'], }, { - formats: [ - 'r32float', - 'rgba8unorm', - 'rgba32float', - 'r8unorm', - 'r8unorm', - ] as GPUTextureFormat[], + formats: ['r32float', 'rgba8unorm', 'rgba32float', 'r8unorm', 'r8unorm'], }, - ]) + ] as const) .beginSubcases() .combine('isAsync', [false, true]) ) diff --git a/src/webgpu/format_info.ts b/src/webgpu/format_info.ts index dca3e1308c78..8ed39cdf3d22 100644 --- a/src/webgpu/format_info.ts +++ b/src/webgpu/format_info.ts @@ -1,5 +1,5 @@ import { keysOf } from '../common/util/data_tables.js'; -import { assert } from '../common/util/util.js'; +import { assert, unreachable } from '../common/util/util.js'; import { align } from './util/math.js'; import { ImageCopyType } from './util/texture/layout.js'; @@ -31,10 +31,6 @@ const kFormatUniversalDefaults = { /** The base format for srgb formats. Specified on both srgb and equivalent non-srgb formats. */ baseFormat: undefined, - /** @deprecated */ - sampleType: undefined, - /** @deprecated */ - copySrc: undefined, /** @deprecated */ copyDst: undefined, /** @deprecated Use `.color.bytes`, `.depth.bytes`, or `.stencil.bytes`. */ @@ -80,7 +76,7 @@ function formatTableWithDefaults u .combine('format', kAllTextureFormats) - .unless(u => kTextureFormatInfo[u.format].sampleType === 'unfilterable-float') + .unless(p => kTextureFormatInfo[p.format].color?.type === 'unfilterable-float') .expand('aspect', u => aspectsForFormat(u.format)) .expand('samples', u => samplesForFormat(u.format)) .beginSubcases() @@ -345,11 +346,8 @@ Parameters: function wgslSampledTextureType(): string { const base = t.params.samples !== 1 ? 'texture_multisampled' : 'texture'; const dimensions = t.params.dimensions.replace('-', '_'); - if (t.params.aspect === 'stencil-only') { - return `${base}_${dimensions}`; - } - const formatInfo = kTextureFormatInfo[t.params.format]; - switch (formatInfo.sampleType) { + const sampleType = sampleTypeForFormatAndAspect(t.params.format, t.params.aspect); + switch (sampleType) { case 'depth': case 'float': return `${base}_${dimensions}`; @@ -389,7 +387,7 @@ Parameters: .params(u => u .combine('format', kAllTextureFormats) - .filter(u => kTextureFormatInfo[u.format].sampleType === 'depth') + .filter(p => !!kTextureFormatInfo[p.format].depth) .expand('aspect', u => aspectsForFormat(u.format)) .unless(u => u.aspect === 'stencil-only') .expand('samples', u => samplesForFormat(u.format)) diff --git a/src/webgpu/util/texture/texel_view.ts b/src/webgpu/util/texture/texel_view.ts index b5f5265d7f33..0b920ef699c1 100644 --- a/src/webgpu/util/texture/texel_view.ts +++ b/src/webgpu/util/texture/texel_view.ts @@ -166,9 +166,13 @@ export class TexelView { const info = kTextureFormatInfo[this.format]; const repr = kTexelRepresentationInfo[this.format]; - const numericToString = numericToStringBuilder( - info.sampleType === 'uint' || info.sampleType === 'sint' - ); + // MAINTENANCE_TODO: Print depth-stencil formats as float+int instead of float+float. + const printAsInteger = info.color + ? // For color, pick the type based on the format type + ['uint', 'sint'].includes(info.color.type) + : // Print depth as "float", depth-stencil as "float,float", stencil as "int". + !info.depth; + const numericToString = numericToStringBuilder(printAsInteger); const componentOrderStr = repr.componentOrder.join(',') + ':'; const subrectCoords = [...fullSubrectCoordinates(subrectOrigin, subrectSize)]; diff --git a/src/webgpu/util/texture/texture_ok.ts b/src/webgpu/util/texture/texture_ok.ts index 5b0f1df7b343..d0267f06278d 100644 --- a/src/webgpu/util/texture/texture_ok.ts +++ b/src/webgpu/util/texture/texture_ok.ts @@ -223,9 +223,13 @@ export function findFailedPixels( const info = kTextureFormatInfo[format]; const repr = kTexelRepresentationInfo[format]; - const numericToString = numericToStringBuilder( - info.sampleType === 'uint' || info.sampleType === 'sint' - ); + // MAINTENANCE_TODO: Print depth-stencil formats as float+int instead of float+float. + const printAsInteger = info.color + ? // For color, pick the type based on the format type + ['uint', 'sint'].includes(info.color.type) + : // Print depth as "float", depth-stencil as "float,float", stencil as "int". + !info.depth; + const numericToString = numericToStringBuilder(printAsInteger); const componentOrderStr = repr.componentOrder.join(',') + ':';