summaryrefslogtreecommitdiffstats
path: root/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts
diff options
context:
space:
mode:
Diffstat (limited to 'dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts')
-rw-r--r--dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts445
1 files changed, 445 insertions, 0 deletions
diff --git a/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts
new file mode 100644
index 0000000000..717a6e2d27
--- /dev/null
+++ b/dom/webgpu/tests/cts/checkout/src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts
@@ -0,0 +1,445 @@
+export const description = `
+Tests for capability checking for features enabling optional texture formats.
+`;
+
+import { makeTestGroup } from '../../../../../common/framework/test_group.js';
+import { assert } from '../../../../../common/util/util.js';
+import { kAllTextureFormats, kTextureFormatInfo } from '../../../../capability_info.js';
+import { kAllCanvasTypes, createCanvas } from '../../../../util/create_elements.js';
+import { ValidationTest } from '../../validation_test.js';
+
+export const g = makeTestGroup(ValidationTest);
+
+const kOptionalTextureFormats = kAllTextureFormats.filter(
+ t => kTextureFormatInfo[t].feature !== undefined
+);
+
+g.test('texture_descriptor')
+ .desc(
+ `
+ Test creating a texture with an optional texture format will fail if the required optional feature
+ is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createTexture({
+ format,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1] as const,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ });
+ });
+
+g.test('texture_descriptor_view_formats')
+ .desc(
+ `
+ Test creating a texture with view formats that have an optional texture format will fail if the
+ required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createTexture({
+ format,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1] as const,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ viewFormats: [format],
+ });
+ });
+ });
+
+g.test('texture_view_descriptor')
+ .desc(
+ `
+ Test creating a texture view with all texture formats will fail if the required optional feature
+ is not enabled.
+ `
+ )
+ .params(u =>
+ u.combine('format', kOptionalTextureFormats).combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ // If the required feature isn't enabled then the texture will fail to create and we won't be
+ // able to test createView, so pick and alternate guaranteed format instead. This will almost
+ // certainly not be view-compatible with the format being tested, but that doesn't matter since
+ // createView should throw an exception due to the format feature not being enabled before it
+ // has a chance to validate that the view and texture formats aren't compatible.
+ const textureFormat = enable_required_feature ? format : 'rgba8unorm';
+
+ const formatInfo = kTextureFormatInfo[format];
+ const testTexture = t.device.createTexture({
+ format: textureFormat,
+ size: [formatInfo.blockWidth, formatInfo.blockHeight, 1] as const,
+ usage: GPUTextureUsage.TEXTURE_BINDING,
+ });
+ const testViewDesc: GPUTextureViewDescriptor = {
+ format,
+ dimension: '2d',
+ aspect: 'all',
+ arrayLayerCount: 1,
+ baseMipLevel: 0,
+ mipLevelCount: 1,
+ baseArrayLayer: 0,
+ };
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ testTexture.createView(testViewDesc);
+ });
+ });
+
+g.test('canvas_configuration')
+ .desc(
+ `
+ Test configuring a canvas with optional texture formats will throw an exception if the required
+ optional feature is not enabled. Otherwise, a validation error should be generated instead of
+ throwing an exception.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, canvasType, enable_required_feature } = t.params;
+
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ const canvasConf = {
+ device: t.device,
+ format,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ };
+
+ if (enable_required_feature) {
+ t.expectValidationError(() => {
+ ctx.configure(canvasConf);
+ });
+ } else {
+ t.shouldThrow('TypeError', () => {
+ ctx.configure(canvasConf);
+ });
+ }
+ });
+
+g.test('canvas_configuration_view_formats')
+ .desc(
+ `
+ Test that configuring a canvas with view formats throws an exception if the required optional
+ feature is not enabled. Otherwise, a validation error should be generated instead of throwing an
+ exception.
+ `
+ )
+ .params(u =>
+ u
+ .combine('viewFormats', [
+ ...kOptionalTextureFormats.map(format => [format]),
+ ['bgra8unorm', 'bc1-rgba-unorm'],
+ ['bc1-rgba-unorm', 'bgra8unorm'],
+ ])
+ .combine('canvasType', kAllCanvasTypes)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { viewFormats, enable_required_feature } = t.params;
+
+ if (enable_required_feature) {
+ t.selectDeviceForTextureFormatOrSkipTestCase(viewFormats as GPUTextureFormat[]);
+ }
+ })
+ .fn(async t => {
+ const { viewFormats, canvasType, enable_required_feature } = t.params;
+
+ const canvas = createCanvas(t, canvasType, 2, 2);
+ const ctx = canvas.getContext('webgpu');
+ assert(ctx instanceof GPUCanvasContext, 'Failed to get WebGPU context from canvas');
+
+ const canvasConf = {
+ device: t.device,
+ format: 'bgra8unorm' as const,
+ usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.COPY_DST,
+ viewFormats: viewFormats as GPUTextureFormat[],
+ };
+
+ if (enable_required_feature) {
+ t.expectValidationError(() => {
+ ctx.configure(canvasConf);
+ });
+ } else {
+ t.shouldThrow('TypeError', () => {
+ ctx.configure(canvasConf);
+ });
+ }
+ });
+
+g.test('storage_texture_binding_layout')
+ .desc(
+ `
+ Test creating a GPUStorageTextureBindingLayout with an optional texture format will fail if the
+ required optional feature are not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting storage.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].storage)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createBindGroupLayout({
+ entries: [
+ {
+ binding: 0,
+ visibility: GPUShaderStage.COMPUTE,
+ storageTexture: {
+ format,
+ },
+ },
+ ],
+ });
+ });
+ });
+
+g.test('color_target_state')
+ .desc(
+ `
+ Test creating a render pipeline with an optional texture format set in GPUColorTargetState will
+ fail if the required optional feature is not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting color rendering.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format }],
+ },
+ });
+ });
+ });
+
+g.test('depth_stencil_state')
+ .desc(
+ `
+ Test creating a render pipeline with an optional texture format set in GPUColorTargetState will
+ fail if the required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(
+ t =>
+ kTextureFormatInfo[t.format].renderable &&
+ (kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil)
+ )
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderPipeline({
+ layout: 'auto',
+ vertex: {
+ module: t.device.createShaderModule({
+ code: `
+ @vertex
+ fn main()-> @builtin(position) vec4<f32> {
+ return vec4<f32>(0.0, 0.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ },
+ depthStencil: {
+ format,
+ },
+ fragment: {
+ module: t.device.createShaderModule({
+ code: `
+ @fragment
+ fn main() -> @location(0) vec4<f32> {
+ return vec4<f32>(0.0, 1.0, 0.0, 1.0);
+ }`,
+ }),
+ entryPoint: 'main',
+ targets: [{ format: 'rgba8unorm' }],
+ },
+ });
+ });
+ });
+
+g.test('render_bundle_encoder_descriptor_color_format')
+ .desc(
+ `
+ Test creating a render bundle encoder with an optional texture format set as one of the color
+ format will fail if the required optional feature is not enabled.
+
+ Note: This test has no cases if there are no optional texture formats supporting color rendering.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(t => kTextureFormatInfo[t.format].renderable && kTextureFormatInfo[t.format].color)
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: [format],
+ });
+ });
+ });
+
+g.test('render_bundle_encoder_descriptor_depth_stencil_format')
+ .desc(
+ `
+ Test creating a render bundle encoder with an optional texture format set as the depth stencil
+ format will fail if the required optional feature is not enabled.
+ `
+ )
+ .params(u =>
+ u
+ .combine('format', kOptionalTextureFormats)
+ .filter(
+ t =>
+ kTextureFormatInfo[t.format].renderable &&
+ (kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil)
+ )
+ .combine('enable_required_feature', [true, false])
+ )
+ .beforeAllSubcases(t => {
+ const { format, enable_required_feature } = t.params;
+
+ const formatInfo = kTextureFormatInfo[format];
+ if (enable_required_feature) {
+ t.selectDeviceOrSkipTestCase(formatInfo.feature);
+ }
+ })
+ .fn(async t => {
+ const { format, enable_required_feature } = t.params;
+
+ t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
+ t.device.createRenderBundleEncoder({
+ colorFormats: ['rgba8unorm'],
+ depthStencilFormat: format,
+ });
+ });
+ });