Skip to content

Commit 5e33111

Browse files
authored
Refactor feature tests for texture formats. (#4202)
Issue #4181
1 parent 5deb620 commit 5e33111

File tree

4 files changed

+85
-44
lines changed

4 files changed

+85
-44
lines changed

src/webgpu/api/operation/limits/max_combined_limits.spec.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ implementation allows, all of them are useable.
1111

1212
import { makeTestGroup } from '../../../../common/framework/test_group.js';
1313
import { range } from '../../../../common/util/util.js';
14-
import { kTextureFormatInfo } from '../../../format_info.js';
14+
import { getColorRenderByteCost } from '../../../format_info.js';
1515
import { AllFeaturesMaxLimitsGPUTest, TextureTestMixin } from '../../../gpu_test.js';
1616
import { TexelView } from '../../../util/texture/texel_view.js';
1717

@@ -31,10 +31,9 @@ g.test('max_storage_buffer_texture_frag_outputs')
3131
const kWidth = 4;
3232
const kHeight = 4;
3333

34-
const info = kTextureFormatInfo[format];
3534
const numColorAttachments = Math.min(
3635
device.limits.maxColorAttachments,
37-
device.limits.maxColorAttachmentBytesPerSample / info.colorRender.byteCost
36+
device.limits.maxColorAttachmentBytesPerSample / getColorRenderByteCost(format)
3837
);
3938
const numStorageBuffers =
4039
device.limits.maxStorageBuffersInFragmentStage ??

src/webgpu/api/validation/capability_checks/features/query_types.spec.ts

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@ Tests for capability checking for features enabling optional query types.
33
`;
44

55
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
6-
import { ValidationTest } from '../../validation_test.js';
6+
import { UniqueFeaturesAndLimitsValidationTest } from '../../validation_test.js';
77

8-
export const g = makeTestGroup(ValidationTest);
8+
export const g = makeTestGroup(UniqueFeaturesAndLimitsValidationTest);
99

1010
g.test('createQuerySet')
1111
.desc(
@@ -77,10 +77,14 @@ g.test('timestamp')
7777
expected = 'TypeError';
7878

7979
const encoder = t.createEncoder('non-pass');
80-
t.shouldThrow(expected, () => {
81-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
82-
(encoder.encoder as any).writeTimestamp(querySet, 0);
83-
});
80+
t.shouldThrow(
81+
expected,
82+
() => {
83+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
84+
(encoder.encoder as any).writeTimestamp(querySet, 0);
85+
},
86+
{ message: 'writeTimestamp should throw' }
87+
);
8488
encoder.finish();
8589
}
8690

src/webgpu/api/validation/capability_checks/features/texture_formats.spec.ts

Lines changed: 30 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,18 @@ import { makeTestGroup } from '../../../../../common/framework/test_group.js';
66
import { getGPU } from '../../../../../common/util/navigator_gpu.js';
77
import { assert } from '../../../../../common/util/util.js';
88
import { kCanvasTextureFormats } from '../../../../capability_info.js';
9-
import { kAllTextureFormats, kTextureFormatInfo } from '../../../../format_info.js';
9+
import {
10+
getBlockInfoForTextureFormat,
11+
getRequiredFeatureForTextureFormat,
12+
isDepthOrStencilTextureFormat,
13+
isTextureFormatPossiblyStorageReadable,
14+
isTextureFormatPossiblyUsableAsColorRenderAttachment,
15+
kOptionalTextureFormats,
16+
} from '../../../../format_info.js';
1017
import { kAllCanvasTypes, createCanvas } from '../../../../util/create_elements.js';
11-
import { ValidationTest } from '../../validation_test.js';
18+
import { UniqueFeaturesAndLimitsValidationTest } from '../../validation_test.js';
1219

13-
export const g = makeTestGroup(ValidationTest);
14-
15-
const kOptionalTextureFormats = kAllTextureFormats.filter(
16-
t => kTextureFormatInfo[t].feature !== undefined
17-
);
20+
export const g = makeTestGroup(UniqueFeaturesAndLimitsValidationTest);
1821

1922
g.test('texture_descriptor')
2023
.desc(
@@ -29,15 +32,14 @@ g.test('texture_descriptor')
2932
.beforeAllSubcases(t => {
3033
const { format, enable_required_feature } = t.params;
3134

32-
const formatInfo = kTextureFormatInfo[format];
3335
if (enable_required_feature) {
34-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
36+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
3537
}
3638
})
3739
.fn(t => {
3840
const { format, enable_required_feature } = t.params;
3941

40-
const formatInfo = kTextureFormatInfo[format];
42+
const formatInfo = getBlockInfoForTextureFormat(format);
4143
t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
4244
t.createTextureTracked({
4345
format,
@@ -60,15 +62,14 @@ g.test('texture_descriptor_view_formats')
6062
.beforeAllSubcases(t => {
6163
const { format, enable_required_feature } = t.params;
6264

63-
const formatInfo = kTextureFormatInfo[format];
6465
if (enable_required_feature) {
65-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
66+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
6667
}
6768
})
6869
.fn(t => {
6970
const { format, enable_required_feature } = t.params;
7071

71-
const formatInfo = kTextureFormatInfo[format];
72+
const formatInfo = getBlockInfoForTextureFormat(format);
7273
t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
7374
t.createTextureTracked({
7475
format,
@@ -92,9 +93,8 @@ g.test('texture_view_descriptor')
9293
.beforeAllSubcases(t => {
9394
const { format, enable_required_feature } = t.params;
9495

95-
const formatInfo = kTextureFormatInfo[format];
9696
if (enable_required_feature) {
97-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
97+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
9898
}
9999
})
100100
.fn(t => {
@@ -107,7 +107,7 @@ g.test('texture_view_descriptor')
107107
// has a chance to validate that the view and texture formats aren't compatible.
108108
const textureFormat = enable_required_feature ? format : 'rgba8unorm';
109109

110-
const formatInfo = kTextureFormatInfo[format];
110+
const formatInfo = getBlockInfoForTextureFormat(format);
111111
const testTexture = t.createTextureTracked({
112112
format: textureFormat,
113113
size: [formatInfo.blockWidth, formatInfo.blockHeight, 1] as const,
@@ -144,9 +144,8 @@ g.test('canvas_configuration')
144144
.beforeAllSubcases(t => {
145145
const { format, enable_required_feature } = t.params;
146146

147-
const formatInfo = kTextureFormatInfo[format];
148147
if (enable_required_feature) {
149-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
148+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
150149
}
151150
})
152151
.fn(t => {
@@ -235,19 +234,19 @@ g.test('storage_texture_binding_layout')
235234
.params(u =>
236235
u
237236
.combine('format', kOptionalTextureFormats)
238-
.filter(t => !!kTextureFormatInfo[t.format].color?.storage)
237+
.filter(t => isTextureFormatPossiblyStorageReadable(t.format))
239238
.combine('enable_required_feature', [true, false])
240239
)
241240
.beforeAllSubcases(t => {
242241
const { format, enable_required_feature } = t.params;
243242

244-
const formatInfo = kTextureFormatInfo[format];
245243
if (enable_required_feature) {
246-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
244+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
247245
}
248246
})
249247
.fn(t => {
250248
const { format, enable_required_feature } = t.params;
249+
t.skipIfTextureFormatNotUsableAsStorageTexture(format);
251250

252251
t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
253252
t.device.createBindGroupLayout({
@@ -277,19 +276,19 @@ g.test('color_target_state')
277276
u
278277
.combine('isAsync', [false, true])
279278
.combine('format', kOptionalTextureFormats)
280-
.filter(t => !!kTextureFormatInfo[t.format].colorRender)
279+
.filter(t => isTextureFormatPossiblyUsableAsColorRenderAttachment(t.format))
281280
.combine('enable_required_feature', [true, false])
282281
)
283282
.beforeAllSubcases(t => {
284283
const { format, enable_required_feature } = t.params;
285284

286-
const formatInfo = kTextureFormatInfo[format];
287285
if (enable_required_feature) {
288-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
286+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
289287
}
290288
})
291289
.fn(t => {
292290
const { isAsync, format, enable_required_feature } = t.params;
291+
t.skipIfTextureFormatNotUsableAsRenderAttachment(format);
293292

294293
t.doCreateRenderPipelineTest(
295294
isAsync,
@@ -333,15 +332,14 @@ g.test('depth_stencil_state')
333332
u
334333
.combine('isAsync', [false, true])
335334
.combine('format', kOptionalTextureFormats)
336-
.filter(t => !!(kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil))
335+
.filter(t => isDepthOrStencilTextureFormat(t.format))
337336
.combine('enable_required_feature', [true, false])
338337
)
339338
.beforeAllSubcases(t => {
340339
const { format, enable_required_feature } = t.params;
341340

342-
const formatInfo = kTextureFormatInfo[format];
343341
if (enable_required_feature) {
344-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
342+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
345343
}
346344
})
347345
.fn(t => {
@@ -395,19 +393,19 @@ g.test('render_bundle_encoder_descriptor_color_format')
395393
.params(u =>
396394
u
397395
.combine('format', kOptionalTextureFormats)
398-
.filter(t => !!kTextureFormatInfo[t.format].colorRender)
396+
.filter(t => isTextureFormatPossiblyUsableAsColorRenderAttachment(t.format))
399397
.combine('enable_required_feature', [true, false])
400398
)
401399
.beforeAllSubcases(t => {
402400
const { format, enable_required_feature } = t.params;
403401

404-
const formatInfo = kTextureFormatInfo[format];
405402
if (enable_required_feature) {
406-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
403+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
407404
}
408405
})
409406
.fn(t => {
410407
const { format, enable_required_feature } = t.params;
408+
t.skipIfTextureFormatNotUsableAsRenderAttachment(format);
411409

412410
t.shouldThrow(enable_required_feature ? false : 'TypeError', () => {
413411
t.device.createRenderBundleEncoder({
@@ -426,15 +424,14 @@ g.test('render_bundle_encoder_descriptor_depth_stencil_format')
426424
.params(u =>
427425
u
428426
.combine('format', kOptionalTextureFormats)
429-
.filter(t => !!(kTextureFormatInfo[t.format].depth || kTextureFormatInfo[t.format].stencil))
427+
.filter(t => isDepthOrStencilTextureFormat(t.format))
430428
.combine('enable_required_feature', [true, false])
431429
)
432430
.beforeAllSubcases(t => {
433431
const { format, enable_required_feature } = t.params;
434432

435-
const formatInfo = kTextureFormatInfo[format];
436433
if (enable_required_feature) {
437-
t.selectDeviceOrSkipTestCase(formatInfo.feature);
434+
t.selectDeviceOrSkipTestCase(getRequiredFeatureForTextureFormat(format));
438435
}
439436
})
440437
.fn(t => {

src/webgpu/format_info.ts

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1554,7 +1554,9 @@ const kTextureFormatInfo_TypeCheck: {
15541554
} = kTextureFormatInfo;
15551555

15561556
// Depth texture formats including formats that also support stencil
1557-
export const kDepthTextureFormats = kDepthStencilFormats.filter(v => kTextureFormatInfo[v].depth);
1557+
export const kDepthTextureFormats = [
1558+
...kDepthStencilFormats.filter(v => kTextureFormatInfo[v].depth),
1559+
] as const;
15581560
// Stencil texture formats including formats that also support depth
15591561
export const kStencilTextureFormats = kDepthStencilFormats.filter(
15601562
v => kTextureFormatInfo[v].stencil
@@ -1580,12 +1582,19 @@ export const kPossibleColorRenderableTextureFormats = [
15801582
...kAllTextureFormats.filter(f => kTextureFormatInfo[f].colorRender),
15811583
'rg11b10ufloat',
15821584
] as const;
1585+
export type PossibleColorRenderTextureFormat =
1586+
(typeof kPossibleColorRenderableTextureFormats)[number];
15831587

15841588
// Texture formats that have a different base format. This is effectively all -srgb formats.
15851589
export const kDifferentBaseFormatTextureFormats = kAllTextureFormats.filter(
15861590
f => kTextureFormatInfo[f].baseFormat && kTextureFormatInfo[f].baseFormat !== f
15871591
);
15881592

1593+
// Textures formats that are optional
1594+
export const kOptionalTextureFormats = kAllTextureFormats.filter(
1595+
t => kTextureFormatInfo[t].feature !== undefined
1596+
);
1597+
15891598
/** Valid GPUTextureFormats for `copyExternalImageToTexture`, by spec. */
15901599
export const kValidTextureFormatsForCopyE2T = [
15911600
'r8unorm',
@@ -1841,6 +1850,21 @@ export function getBlockInfoForTextureFormat(format: GPUTextureFormat) {
18411850
};
18421851
}
18431852

1853+
/**
1854+
* Returns the "byteCost" of rendering to a color texture format.
1855+
* MAINTENANCE_TODO: remove `rg11b10ufloat' from here and add its data to table
1856+
* once CTS is refactored. See issue #4181
1857+
*/
1858+
export function getColorRenderByteCost(format: PossibleColorRenderTextureFormat) {
1859+
const byteCost =
1860+
format === 'rg11b10ufloat' ? 8 : kTextureFormatInfo[format].colorRender?.byteCost;
1861+
// MAINTENANCE_TODO: remove this assert. The issue is typescript thinks
1862+
// PossibleColorRenderTextureFormat contains all texture formats and not just
1863+
// a filtered list.
1864+
assert(byteCost !== undefined);
1865+
return byteCost;
1866+
}
1867+
18441868
/**
18451869
* Gets the baseFormat for a texture format.
18461870
*/
@@ -1931,6 +1955,15 @@ export function isTextureFormatPossiblyUsableAsRenderAttachment(format: GPUTextu
19311955
return format === 'rg11b10ufloat' || isDepthOrStencilTextureFormat(format) || !!info.colorRender;
19321956
}
19331957

1958+
/**
1959+
* Returns true if a texture can possibly be used as a color render attachment.
1960+
* The texture may require certain features to be enabled.
1961+
*/
1962+
export function isTextureFormatPossiblyUsableAsColorRenderAttachment(format: GPUTextureFormat) {
1963+
const info = kTextureFormatInfo[format];
1964+
return format === 'rg11b10ufloat' || !!info.colorRender;
1965+
}
1966+
19341967
/**
19351968
* Returns true if a texture can possibly be used multisampled.
19361969
* The texture may require certain features to be enabled.
@@ -1940,12 +1973,20 @@ export function isTextureFormatPossiblyMultisampled(format: GPUTextureFormat) {
19401973
return format === 'rg11b10ufloat' || info.multisample;
19411974
}
19421975

1976+
/**
1977+
* Returns true if a texture can possibly be used as a storage texture.
1978+
* The texture may require certain features to be enabled.
1979+
*/
1980+
export function isTextureFormatPossiblyStorageReadable(format: GPUTextureFormat) {
1981+
return !!kTextureFormatInfo[format].color?.storage;
1982+
}
1983+
19431984
/**
19441985
* Returns true if a texture can possibly be used as a writable storage texture.
19451986
* The texture may require certain features to be enabled.
19461987
*/
19471988
export function isTextureFormatPossiblyStorageWritable(format: GPUTextureFormat) {
1948-
return kTextureFormatInfo[format].color?.readWriteStorage;
1989+
return !!kTextureFormatInfo[format].color?.readWriteStorage;
19491990
}
19501991

19511992
export function is16Float(format: GPUTextureFormat) {

0 commit comments

Comments
 (0)