Skip to content

Commit 1a34648

Browse files
authored
Refactor src/webpgu/api/validation/encoding and a few extra (gpuweb#4273)
Issue gpuweb#4181 Issue gpuweb#4178 Note: For copyTextureToTexture:texture_format_compatibility it was not at all clear to me why it was choosing textures with features. AFAICT that was testing almost nothing. Refactored it.
1 parent 4ebc81d commit 1a34648

27 files changed

+179
-265
lines changed

src/webgpu/api/validation/encoding/beginComputePass.spec.ts

+7-15
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ Tests for validation in beginComputePass and GPUComputePassDescriptor as its opt
44

55
import { makeTestGroup } from '../../../../common/framework/test_group.js';
66
import { kQueryTypes } from '../../../capability_info.js';
7-
import { ValidationTest } from '../validation_test.js';
7+
import { AllFeaturesMaxLimitsValidationTest } from '../validation_test.js';
88

9-
class F extends ValidationTest {
9+
class F extends AllFeaturesMaxLimitsValidationTest {
1010
tryComputePass(success: boolean, descriptor: GPUComputePassDescriptor): void {
1111
const encoder = this.device.createCommandEncoder();
1212
const computePass = encoder.beginComputePass(descriptor);
@@ -31,11 +31,9 @@ g.test('timestampWrites,query_set_type')
3131
u //
3232
.combine('queryType', kQueryTypes)
3333
)
34-
.beforeAllSubcases(t => {
35-
t.selectDeviceForQueryTypeOrSkipTestCase(['timestamp', t.params.queryType]);
36-
})
3734
.fn(t => {
3835
const { queryType } = t.params;
36+
t.skipIfDeviceDoesNotSupportQueryType(queryType);
3937

4038
const isValid = queryType === 'timestamp';
4139

@@ -55,10 +53,8 @@ g.test('timestampWrites,query_set_type')
5553
g.test('timestampWrites,invalid_query_set')
5654
.desc(`Tests that timestampWrite that has an invalid query set generates a validation error.`)
5755
.params(u => u.combine('querySetState', ['valid', 'invalid'] as const))
58-
.beforeAllSubcases(t => {
59-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
60-
})
6156
.fn(t => {
57+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
6258
const { querySetState } = t.params;
6359

6460
const querySet = t.createQuerySetWithState(querySetState, {
@@ -88,10 +84,8 @@ g.test('timestampWrites,query_index')
8884
.combine('beginningOfPassWriteIndex', [undefined, 0, 1, 2, 3] as const)
8985
.combine('endOfPassWriteIndex', [undefined, 0, 1, 2, 3] as const)
9086
)
91-
.beforeAllSubcases(t => {
92-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
93-
})
9487
.fn(t => {
88+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
9589
const { beginningOfPassWriteIndex, endOfPassWriteIndex } = t.params;
9690

9791
const querySetCount = 2;
@@ -121,11 +115,9 @@ g.test('timestamp_query_set,device_mismatch')
121115
`
122116
)
123117
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
124-
.beforeAllSubcases(t => {
125-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
126-
t.selectMismatchedDeviceOrSkipTestCase('timestamp-query');
127-
})
118+
.beforeAllSubcases(t => t.usesMismatchedDevice())
128119
.fn(t => {
120+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
129121
const { mismatched } = t.params;
130122
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
131123

src/webgpu/api/validation/encoding/beginRenderPass.spec.ts

+7-15
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ Notes:
2222
`;
2323

2424
import { makeTestGroup } from '../../../../common/framework/test_group.js';
25-
import { ValidationTest } from '../validation_test.js';
25+
import { AllFeaturesMaxLimitsValidationTest } from '../validation_test.js';
2626

27-
export const g = makeTestGroup(ValidationTest);
27+
export const g = makeTestGroup(AllFeaturesMaxLimitsValidationTest);
2828

2929
g.test('color_attachments,device_mismatch')
3030
.desc(
@@ -62,9 +62,7 @@ g.test('color_attachments,device_mismatch')
6262
target1Mismatched: true,
6363
},
6464
])
65-
.beforeAllSubcases(t => {
66-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
67-
})
65+
.beforeAllSubcases(t => t.usesMismatchedDevice())
6866
.fn(t => {
6967
const { view0Mismatched, target0Mismatched, view1Mismatched, target1Mismatched } = t.params;
7068
const mismatched = view0Mismatched || target0Mismatched || view1Mismatched || target1Mismatched;
@@ -111,9 +109,7 @@ g.test('depth_stencil_attachment,device_mismatch')
111109
'Tests beginRenderPass cannot be called with a depth stencil attachment whose texture view is created from another device'
112110
)
113111
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
114-
.beforeAllSubcases(t => {
115-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
116-
})
112+
.beforeAllSubcases(t => t.usesMismatchedDevice())
117113
.fn(t => {
118114
const { mismatched } = t.params;
119115

@@ -150,9 +146,7 @@ g.test('occlusion_query_set,device_mismatch')
150146
'Tests beginRenderPass cannot be called with an occlusion query set created from another device'
151147
)
152148
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
153-
.beforeAllSubcases(t => {
154-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
155-
})
149+
.beforeAllSubcases(t => t.usesMismatchedDevice())
156150
.fn(t => {
157151
const { mismatched } = t.params;
158152
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
@@ -175,11 +169,9 @@ g.test('timestamp_query_set,device_mismatch')
175169
`
176170
)
177171
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
178-
.beforeAllSubcases(t => {
179-
t.selectDeviceOrSkipTestCase(['timestamp-query']);
180-
t.selectMismatchedDeviceOrSkipTestCase('timestamp-query');
181-
})
172+
.beforeAllSubcases(t => t.usesMismatchedDevice())
182173
.fn(t => {
174+
t.skipIfDeviceDoesNotSupportQueryType('timestamp');
183175
const { mismatched } = t.params;
184176
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
185177

src/webgpu/api/validation/encoding/cmds/clearBuffer.spec.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@ import { makeTestGroup } from '../../../../../common/framework/test_group.js';
66
import { kBufferUsages } from '../../../../capability_info.js';
77
import { kResourceStates } from '../../../../gpu_test.js';
88
import { kMaxSafeMultipleOf8 } from '../../../../util/math.js';
9-
import { ValidationTest } from '../../validation_test.js';
9+
import { AllFeaturesMaxLimitsValidationTest } from '../../validation_test.js';
1010

11-
class F extends ValidationTest {
11+
class F extends AllFeaturesMaxLimitsValidationTest {
1212
TestClearBuffer(options: {
1313
buffer: GPUBuffer;
1414
offset: number | undefined;
@@ -57,9 +57,7 @@ g.test('buffer_state')
5757
g.test('buffer,device_mismatch')
5858
.desc(`Tests clearBuffer cannot be called with buffer created from another device.`)
5959
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
60-
.beforeAllSubcases(t => {
61-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
62-
})
60+
.beforeAllSubcases(t => t.usesMismatchedDevice())
6361
.fn(t => {
6462
const { mismatched } = t.params;
6563
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;

src/webgpu/api/validation/encoding/cmds/compute_pass.spec.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ import { makeValueTestVariant } from '../../../../../common/util/util.js';
99
import { kBufferUsages } from '../../../../capability_info.js';
1010
import { GPUConst } from '../../../../constants.js';
1111
import { kResourceStates, ResourceState } from '../../../../gpu_test.js';
12-
import { ValidationTest } from '../../validation_test.js';
12+
import { AllFeaturesMaxLimitsValidationTest } from '../../validation_test.js';
1313

14-
class F extends ValidationTest {
14+
class F extends AllFeaturesMaxLimitsValidationTest {
1515
createComputePipeline(state: 'valid' | 'invalid'): GPUComputePipeline {
1616
if (state === 'valid') {
1717
return this.createNoOpComputePipeline();
@@ -67,9 +67,7 @@ setPipeline should generate an error iff using an 'invalid' pipeline.
6767
g.test('pipeline,device_mismatch')
6868
.desc('Tests setPipeline cannot be called with a compute pipeline created from another device')
6969
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
70-
.beforeAllSubcases(t => {
71-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
72-
})
70+
.beforeAllSubcases(t => t.usesMismatchedDevice())
7371
.fn(t => {
7472
const { mismatched } = t.params;
7573
const sourceDevice = mismatched ? t.mismatchedDevice : t.device;
@@ -193,9 +191,7 @@ g.test('indirect_dispatch_buffer,device_mismatch')
193191
`Tests dispatchWorkgroupsIndirect cannot be called with an indirect buffer created from another device`
194192
)
195193
.paramsSubcasesOnly(u => u.combine('mismatched', [true, false]))
196-
.beforeAllSubcases(t => {
197-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
198-
})
194+
.beforeAllSubcases(t => t.usesMismatchedDevice())
199195
.fn(t => {
200196
const { mismatched } = t.params;
201197

src/webgpu/api/validation/encoding/cmds/copyBufferToBuffer.spec.ts

+3-5
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ import { makeTestGroup } from '../../../../../common/framework/test_group.js';
2727
import { kBufferUsages } from '../../../../capability_info.js';
2828
import { kResourceStates } from '../../../../gpu_test.js';
2929
import { kMaxSafeMultipleOf8 } from '../../../../util/math.js';
30-
import { ValidationTest } from '../../validation_test.js';
30+
import { AllFeaturesMaxLimitsValidationTest } from '../../validation_test.js';
3131

32-
class F extends ValidationTest {
32+
class F extends AllFeaturesMaxLimitsValidationTest {
3333
TestCopyBufferToBuffer(options: {
3434
srcBuffer: GPUBuffer;
3535
srcOffset: number;
@@ -102,9 +102,7 @@ g.test('buffer,device_mismatch')
102102
{ srcMismatched: true, dstMismatched: false },
103103
{ srcMismatched: false, dstMismatched: true },
104104
] as const)
105-
.beforeAllSubcases(t => {
106-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
107-
})
105+
.beforeAllSubcases(t => t.usesMismatchedDevice())
108106
.fn(t => {
109107
const { srcMismatched, dstMismatched } = t.params;
110108

src/webgpu/api/validation/encoding/cmds/copyTextureToTexture.spec.ts

+41-53
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,21 @@ copyTextureToTexture tests.
55
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
66
import { kTextureUsages, kTextureDimensions } from '../../../../capability_info.js';
77
import {
8-
kTextureFormatInfo,
98
kAllTextureFormats,
109
kCompressedTextureFormats,
1110
kDepthStencilFormats,
12-
kFeaturesForFormats,
13-
filterFormatsByFeature,
1411
textureDimensionAndFormatCompatible,
12+
getBlockInfoForTextureFormat,
13+
getBaseFormatForTextureFormat,
14+
canCopyFromAllAspectsOfTextureFormat,
15+
canCopyToAllAspectsOfTextureFormat,
16+
ColorTextureFormat,
1517
} from '../../../../format_info.js';
1618
import { kResourceStates } from '../../../../gpu_test.js';
1719
import { align, lcm } from '../../../../util/math.js';
18-
import { ValidationTest } from '../../validation_test.js';
20+
import { AllFeaturesMaxLimitsValidationTest } from '../../validation_test.js';
1921

20-
class F extends ValidationTest {
22+
class F extends AllFeaturesMaxLimitsValidationTest {
2123
TestCopyTextureToTexture(
2224
source: GPUTexelCopyTextureInfo,
2325
destination: GPUTexelCopyTextureInfo,
@@ -45,13 +47,11 @@ class F extends ValidationTest {
4547
format: GPUTextureFormat,
4648
mipLevel: number
4749
): Required<GPUExtent3DDict> {
50+
const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format);
4851
const virtualWidthAtLevel = Math.max(textureSize.width >> mipLevel, 1);
4952
const virtualHeightAtLevel = Math.max(textureSize.height >> mipLevel, 1);
50-
const physicalWidthAtLevel = align(virtualWidthAtLevel, kTextureFormatInfo[format].blockWidth);
51-
const physicalHeightAtLevel = align(
52-
virtualHeightAtLevel,
53-
kTextureFormatInfo[format].blockHeight
54-
);
53+
const physicalWidthAtLevel = align(virtualWidthAtLevel, blockWidth);
54+
const physicalHeightAtLevel = align(virtualHeightAtLevel, blockHeight);
5555

5656
switch (dimension) {
5757
case '1d':
@@ -118,9 +118,7 @@ g.test('texture,device_mismatch')
118118
{ srcMismatched: true, dstMismatched: false },
119119
{ srcMismatched: false, dstMismatched: true },
120120
] as const)
121-
.beforeAllSubcases(t => {
122-
t.selectMismatchedDeviceOrSkipTestCase(undefined);
123-
})
121+
.beforeAllSubcases(t => t.usesMismatchedDevice())
124122
.fn(t => {
125123
const { srcMismatched, dstMismatched } = t.params;
126124

@@ -358,28 +356,26 @@ Test the formats of textures in copyTextureToTexture must be copy-compatible.
358356
)
359357
.params(u =>
360358
u
361-
.combine('srcFormatFeature', kFeaturesForFormats)
362-
.combine('dstFormatFeature', kFeaturesForFormats)
363-
.beginSubcases()
364-
.expand('srcFormat', ({ srcFormatFeature }) =>
365-
filterFormatsByFeature(srcFormatFeature, kAllTextureFormats)
366-
)
367-
.expand('dstFormat', ({ dstFormatFeature }) =>
368-
filterFormatsByFeature(dstFormatFeature, kAllTextureFormats)
369-
)
359+
.combine('srcFormat', kAllTextureFormats)
360+
.filter(t => canCopyFromAllAspectsOfTextureFormat(t.srcFormat))
361+
.combine('dstFormat', kAllTextureFormats)
362+
.filter(t => canCopyToAllAspectsOfTextureFormat(t.dstFormat))
363+
.filter(t => {
364+
const srcInfo = getBlockInfoForTextureFormat(t.srcFormat);
365+
const dstInfo = getBlockInfoForTextureFormat(t.dstFormat);
366+
return (
367+
srcInfo.blockWidth === dstInfo.blockWidth && srcInfo.blockHeight === dstInfo.blockHeight
368+
);
369+
})
370370
)
371-
.beforeAllSubcases(t => {
372-
const { srcFormatFeature, dstFormatFeature } = t.params;
373-
t.selectDeviceOrSkipTestCase([srcFormatFeature, dstFormatFeature]);
374-
})
375371
.fn(t => {
376372
const { srcFormat, dstFormat } = t.params;
377373

378-
t.skipIfTextureFormatNotSupportedDeprecated(srcFormat, dstFormat);
379-
t.skipIfCopyTextureToTextureNotSupportedForFormatDeprecated(srcFormat, dstFormat);
374+
t.skipIfTextureFormatNotSupported(srcFormat, dstFormat);
375+
t.skipIfCopyTextureToTextureNotSupportedForFormat(srcFormat, dstFormat);
380376

381-
const srcFormatInfo = kTextureFormatInfo[srcFormat];
382-
const dstFormatInfo = kTextureFormatInfo[dstFormat];
377+
const srcFormatInfo = getBlockInfoForTextureFormat(srcFormat);
378+
const dstFormatInfo = getBlockInfoForTextureFormat(dstFormat);
383379

384380
const textureSize = {
385381
width: lcm(srcFormatInfo.blockWidth, dstFormatInfo.blockWidth),
@@ -400,8 +396,10 @@ Test the formats of textures in copyTextureToTexture must be copy-compatible.
400396
});
401397

402398
// Allow copy between compatible format textures.
403-
const srcBaseFormat = kTextureFormatInfo[srcFormat].baseFormat ?? srcFormat;
404-
const dstBaseFormat = kTextureFormatInfo[dstFormat].baseFormat ?? dstFormat;
399+
const srcBaseFormat =
400+
getBaseFormatForTextureFormat(srcFormat as ColorTextureFormat) ?? srcFormat;
401+
const dstBaseFormat =
402+
getBaseFormatForTextureFormat(dstFormat as ColorTextureFormat) ?? dstFormat;
405403
const isSuccess = srcBaseFormat === dstBaseFormat;
406404

407405
t.TestCopyTextureToTexture(
@@ -448,13 +446,10 @@ Note: this is only tested for 2D textures as it is the only dimension compatible
448446
.combine('srcCopyLevel', [1, 2])
449447
.combine('dstCopyLevel', [0, 1])
450448
)
451-
.beforeAllSubcases(t => {
452-
const { format } = t.params;
453-
t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
454-
})
455449
.fn(t => {
456450
const { format, copyBoxOffsets, srcTextureSize, dstTextureSize, srcCopyLevel, dstCopyLevel } =
457451
t.params;
452+
t.skipIfTextureFormatNotSupported(format);
458453
const kMipLevelCount = 3;
459454

460455
const srcTexture = t.createTextureTracked({
@@ -704,12 +699,9 @@ Test the validations on the member 'aspect' of GPUTexelCopyTextureInfo in CopyTe
704699
.combine('sourceAspect', ['all', 'depth-only', 'stencil-only'] as const)
705700
.combine('destinationAspect', ['all', 'depth-only', 'stencil-only'] as const)
706701
)
707-
.beforeAllSubcases(t => {
708-
const { format } = t.params;
709-
t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
710-
})
711702
.fn(t => {
712703
const { format, sourceAspect, destinationAspect } = t.params;
704+
t.skipIfTextureFormatNotSupported(format);
713705

714706
const kTextureSize = { width: 16, height: 8, depthOrArrayLayers: 1 };
715707

@@ -783,14 +775,13 @@ TODO: Express the offsets in "block size" so as to be able to test non-4x4 compr
783775
.combine('srcCopyLevel', [0, 1, 2])
784776
.combine('dstCopyLevel', [0, 1, 2])
785777
)
786-
.beforeAllSubcases(t => {
787-
const { format } = t.params;
788-
t.selectDeviceOrSkipTestCase(kTextureFormatInfo[format].feature);
789-
t.skipIfCopyTextureToTextureNotSupportedForFormat(format);
790-
})
791778
.fn(t => {
792779
const { format, dimension, copyBoxOffsets, srcCopyLevel, dstCopyLevel } = t.params;
793-
const { blockWidth, blockHeight } = kTextureFormatInfo[format];
780+
781+
t.skipIfTextureFormatNotSupported(format);
782+
t.skipIfCopyTextureToTextureNotSupportedForFormat(format);
783+
784+
const { blockWidth, blockHeight } = getBlockInfoForTextureFormat(format);
794785

795786
const kTextureSize = {
796787
width: 15 * blockWidth,
@@ -840,14 +831,11 @@ TODO: Express the offsets in "block size" so as to be able to test non-4x4 compr
840831
const copyDepth =
841832
kTextureSize.depthOrArrayLayers + copyBoxOffsets.depthOrArrayLayers - copyOrigin.z;
842833

843-
const texelBlockWidth = kTextureFormatInfo[format].blockWidth;
844-
const texelBlockHeight = kTextureFormatInfo[format].blockHeight;
845-
846834
const isSuccessForCompressedFormats =
847-
copyOrigin.x % texelBlockWidth === 0 &&
848-
copyOrigin.y % texelBlockHeight === 0 &&
849-
copyWidth % texelBlockWidth === 0 &&
850-
copyHeight % texelBlockHeight === 0;
835+
copyOrigin.x % blockWidth === 0 &&
836+
copyOrigin.y % blockHeight === 0 &&
837+
copyWidth % blockWidth === 0 &&
838+
copyHeight % blockHeight === 0;
851839

852840
{
853841
const isSuccess =

src/webgpu/api/validation/encoding/cmds/debug.spec.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ Test Coverage:
1515

1616
import { makeTestGroup } from '../../../../../common/framework/test_group.js';
1717
import { kEncoderTypes } from '../../../../util/command_buffer_maker.js';
18-
import { ValidationTest } from '../../validation_test.js';
18+
import { AllFeaturesMaxLimitsValidationTest } from '../../validation_test.js';
1919

20-
export const g = makeTestGroup(ValidationTest);
20+
export const g = makeTestGroup(AllFeaturesMaxLimitsValidationTest);
2121

2222
g.test('debug_group_balanced')
2323
.params(u =>

0 commit comments

Comments
 (0)