export const description = `
Tests for capabilities added by bgra8unorm-storage flag.
`;
import { makeTestGroup } from '../../../../common/framework/test_group.js';
import { assert } from '../../../../common/util/util.js';
import {
kTextureUsages,
kValidCombinationsOfOneOrTwoTextureUsages,
usageIsTypeErrorForConfigure,
} from '../../../capability_info.js';
import { GPUConst } from '../../../constants.js';
import { UniqueFeaturesOrLimitsGPUTest } from '../../../gpu_test.js';
import { kAllCanvasTypes, createCanvas } from '../../../util/create_elements.js';
class BGRA8UnormStorageValidationTests extends UniqueFeaturesOrLimitsGPUTest {
testCreateShaderModuleWithBGRA8UnormStorage(
shaderType: 'fragment' | 'compute',
success: boolean
): void {
let shaderDeclaration = '';
switch (shaderType) {
case 'fragment':
shaderDeclaration = '@fragment';
break;
case 'compute':
shaderDeclaration = '@compute @workgroup_size(1)';
break;
}
this.expectValidationError(() => {
this.device.createShaderModule({
code: `
@group(0) @binding(1) var outputTex: texture_storage_2d<bgra8unorm, write>;
${shaderDeclaration} fn main() {
textureStore(outputTex, vec2<i32>(), vec4<f32>());
}
`,
});
}, !success);
}
}
export const g = makeTestGroup(BGRA8UnormStorageValidationTests);
g.test('create_texture')
.desc(
`
Test that it is valid to create bgra8unorm texture with STORAGE usage iff the feature
bgra8unorm-storage is enabled. Note, the createTexture test suite covers the validation cases where
this feature is not enabled, which are skipped here.
`
)
.beforeAllSubcases(t => {
t.selectDeviceOrSkipTestCase('bgra8unorm-storage');
})
.fn(t => {
const descriptor = {
size: [1, 1, 1],
format: 'bgra8unorm' as const,
usage: GPUConst.TextureUsage.STORAGE_BINDING,
};
t.createTextureTracked(descriptor);
});
g.test('create_bind_group_layout')
.desc(
`
Test that it is valid to create GPUBindGroupLayout that uses bgra8unorm as storage texture format
iff the feature bgra8unorm-storage is enabled. Note, the createBindGroupLayout test suite covers the
validation cases where this feature is not enabled, which are skipped here.
`
)
.beforeAllSubcases(t => {
t.selectDeviceOrSkipTestCase('bgra8unorm-storage');
})
.fn(t => {
t.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.COMPUTE,
storageTexture: { format: 'bgra8unorm' },
},
],
});
});
g.test('configure_storage_usage_on_canvas_context_without_bgra8unorm_storage')
.desc(
`
Test that it is invalid to configure a GPUCanvasContext to 'GPUStorageBinding' usage with
'bgra8unorm' format on a GPUDevice with 'bgra8unorm-storage' disabled.
`
)
.params(u =>
u
.combine('canvasType', kAllCanvasTypes)
.beginSubcases()
.combine(
'usage',
kValidCombinationsOfOneOrTwoTextureUsages
.filter(usage => !usageIsTypeErrorForConfigure(usage))
)
)
.fn(t => {
const { canvasType, usage } = t.params;
if ((usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0) {
t.skipIfTransientAttachmentNotSupported();
}
const canvas = createCanvas(t, canvasType, 1, 1);
const ctx = canvas.getContext('webgpu');
assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
const requiredStorageBinding = !!(usage & GPUTextureUsage.STORAGE_BINDING);
t.expectValidationError(() => {
ctx.configure({
device: t.device,
format: 'bgra8unorm',
usage,
});
}, requiredStorageBinding);
});
g.test('configure_storage_usage_on_canvas_context_with_bgra8unorm_storage')
.desc(
`
Test that it is valid to configure a GPUCanvasContext with GPUStorageBinding usage and a GPUDevice
with 'bgra8unorm-storage' enabled.
`
)
.beforeAllSubcases(t => {
t.selectDeviceOrSkipTestCase({
requiredFeatures: ['bgra8unorm-storage'],
requiredLimits: {
maxStorageTexturesInFragmentStage: 1,
},
});
})
.params(u =>
u
.combine('canvasType', kAllCanvasTypes)
.beginSubcases()
.combine(
'usage',
kTextureUsages
.filter(usage => !usageIsTypeErrorForConfigure(usage))
.map(usage => usage | GPUConst.TextureUsage.STORAGE_BINDING)
)
)
.fn(t => {
const { canvasType, usage } = t.params;
if ((usage & GPUConst.TextureUsage.TRANSIENT_ATTACHMENT) !== 0) {
t.skipIfTransientAttachmentNotSupported();
}
const canvas = createCanvas(t, canvasType, 1, 1);
const ctx = canvas.getContext('webgpu');
assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
ctx.configure({
device: t.device,
format: 'bgra8unorm',
usage,
});
const currentTexture = ctx.getCurrentTexture();
const bindGroupLayout = t.device.createBindGroupLayout({
entries: [
{
binding: 0,
visibility: GPUShaderStage.FRAGMENT,
storageTexture: { access: 'write-only', format: currentTexture.format },
},
],
});
t.device.createBindGroup({
layout: bindGroupLayout,
entries: [
{
binding: 0,
resource: currentTexture.createView(),
},
],
});
});