export const description = ` Tests that, in compat mode, the dimension of a view is compatible with a texture's textureBindingViewDimension. `; import { makeTestGroup } from '../../../../common/framework/test_group.js'; import { kTextureDimensions, kTextureViewDimensions } from '../../../capability_info.js'; import { effectiveViewDimensionForTexture, getTextureDimensionFromView, } from '../../../util/texture/base.js'; import { CompatibilityTest } from '../../compatibility_test.js'; export const g = makeTestGroup(CompatibilityTest); function isTextureBindingViewDimensionCompatibleWithDimension( dimension: GPUTextureDimension = '2d', textureBindingViewDimension: GPUTextureViewDimension = '2d' ) { return getTextureDimensionFromView(textureBindingViewDimension) === dimension; } function isValidViewDimensionForDimension( dimension: GPUTextureDimension | undefined, depthOrArrayLayers: number, viewDimension: GPUTextureViewDimension | undefined ) { if (viewDimension === undefined) { return true; } switch (dimension) { case '1d': return viewDimension === '1d'; case '2d': case undefined: switch (viewDimension) { case undefined: case '2d': case '2d-array': return true; case 'cube': return depthOrArrayLayers === 6; case 'cube-array': return depthOrArrayLayers % 6 === 0; default: return false; } break; case '3d': return viewDimension === '3d'; } } function isValidDimensionForDepthOrArrayLayers( dimension: GPUTextureDimension | undefined, depthOrArrayLayers: number ) { switch (dimension) { case '1d': return depthOrArrayLayers === 1; default: return true; } } function isValidViewDimensionForDepthOrArrayLayers( viewDimension: GPUTextureViewDimension | undefined, depthOrArrayLayers: number ) { switch (viewDimension) { case '2d': return depthOrArrayLayers === 1; case 'cube': return depthOrArrayLayers === 6; case 'cube-array': return depthOrArrayLayers % 6 === 0; default: return true; } return viewDimension === 'cube'; } function getEffectiveTextureBindingViewDimension( dimension: GPUTextureDimension | undefined, depthOrArrayLayers: number, textureBindingViewDimension: GPUTextureViewDimension | undefined ) { if (textureBindingViewDimension) { return textureBindingViewDimension; } switch (dimension) { case '1d': return '1d'; case '2d': case undefined: return depthOrArrayLayers > 1 ? '2d-array' : '2d'; break; case '3d': return '3d'; } } g.test('viewDimension_matches_textureBindingViewDimension') .desc( ` Tests that, in compat mode, the dimension of a view is compatible with a texture's textureBindingViewDimension when used as a TEXTURE_BINDING. ` ) .params(u => u // .combine('dimension', [...kTextureDimensions, undefined]) .combine('textureBindingViewDimension', [...kTextureViewDimensions, undefined]) .combine('viewDimension', [...kTextureViewDimensions, undefined]) .combine('depthOrArrayLayers', [1, 2, 6]) .filter( ({ dimension, textureBindingViewDimension, depthOrArrayLayers, viewDimension }) => textureBindingViewDimension !== 'cube-array' && viewDimension !== 'cube-array' && isTextureBindingViewDimensionCompatibleWithDimension( dimension, textureBindingViewDimension ) && isValidViewDimensionForDimension(dimension, depthOrArrayLayers, viewDimension) && isValidViewDimensionForDepthOrArrayLayers( textureBindingViewDimension, depthOrArrayLayers ) && isValidDimensionForDepthOrArrayLayers(dimension, depthOrArrayLayers) ) ) .fn(t => { const { dimension, textureBindingViewDimension, viewDimension, depthOrArrayLayers } = t.params; const texture = t.createTextureTracked({ size: [1, 1, depthOrArrayLayers], format: 'rgba8unorm', usage: GPUTextureUsage.TEXTURE_BINDING, ...(dimension && { dimension }), ...(textureBindingViewDimension && { textureBindingViewDimension }), }); const effectiveTextureBindingViewDimension = getEffectiveTextureBindingViewDimension( dimension, texture.depthOrArrayLayers, textureBindingViewDimension ); const effectiveViewDimension = getEffectiveTextureBindingViewDimension( dimension, texture.depthOrArrayLayers, viewDimension ); const layout = t.device.createBindGroupLayout({ entries: [ { binding: 0, visibility: GPUShaderStage.COMPUTE, texture: { viewDimension: effectiveViewDimensionForTexture(texture, viewDimension), }, }, ], }); const resource = texture.createView({ dimension: viewDimension }); const shouldError = effectiveTextureBindingViewDimension !== effectiveViewDimension; t.expectValidationErrorInCompatibilityMode(() => { t.device.createBindGroup({ layout, entries: [{ binding: 0, resource }], }); }, shouldError); });