Skip to content

Commit

Permalink
Compat: Make compat tests run on core and expect to pass (gpuweb#3775)
Browse files Browse the repository at this point in the history
This helps validate the tests are doing something that is supposed
to pass on core but fail on compat.

This refactor found one bug in createTexture where it was failing
because it was asking for a depthOrArrayLayers = 6 1D texture
  • Loading branch information
greggman authored May 31, 2024
1 parent 5fb5afd commit 5c23d90
Show file tree
Hide file tree
Showing 12 changed files with 47 additions and 26 deletions.
2 changes: 1 addition & 1 deletion src/webgpu/compat/api/validation/createBindGroup.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ g.test('viewDimension_matches_textureBindingViewDimension')
const resource = texture.createView({ dimension: viewDimension });
const shouldError = effectiveTextureBindingViewDimension !== effectiveViewDimension;

t.expectValidationError(() => {
t.expectValidationErrorInCompatibilityMode(() => {
t.device.createBindGroup({
layout,
entries: [{ binding: 0, resource }],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ g.test('unsupportedStorageTextureFormats')
.fn(t => {
const { format } = t.params;

t.expectValidationError(() => {
t.expectValidationErrorInCompatibilityMode(() => {
t.device.createBindGroupLayout({
entries: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ g.test('compressed')

const encoder = t.device.createCommandEncoder();
encoder.copyTextureToBuffer({ texture }, { buffer, bytesPerRow }, textureSize);
t.expectGPUError('validation', () => {
t.expectGPUErrorInCompatibilityMode('validation', () => {
encoder.finish();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ g.test('compressed')
blockHeight,
1,
]);
t.expectGPUError('validation', () => {
t.expectGPUErrorInCompatibilityMode('validation', () => {
encoder.finish();
});
});
Expand Down Expand Up @@ -88,7 +88,7 @@ g.test('multisample')
blockHeight,
1,
]);
t.expectGPUError('validation', () => {
t.expectGPUErrorInCompatibilityMode('validation', () => {
encoder.finish();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ Tests that you can not use 2 different views of the same texture in a render pas
encoder.setPipeline(pipeline);
const { shouldSucceed } = fn(t.device, pipeline, encoder, texture);
kDrawUseCases[useCase](t, encoder as GPURenderCommandsMixin);
validateFinish(shouldSucceed);
validateFinish(!t.isCompatibility || shouldSucceed);
});

g.test('twoDifferentTextureViews,render_pass,unused')
Expand Down Expand Up @@ -399,7 +399,7 @@ Tests that you can not use 2 different views of the same texture in a compute pa
encoder.setPipeline(pipeline);
const { shouldSucceed } = fn(t.device, pipeline, encoder, texture);
kDispatchUseCases[useCase](t, encoder);
validateFinish(shouldSucceed);
validateFinish(!t.isCompatibility || shouldSucceed);
});

g.test('twoDifferentTextureViews,compute_pass,unused')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,6 @@ g.test('depthBiasClamp')
},
};

const success = !depthBiasClamp;
const success = !t.isCompatibility || !depthBiasClamp;
t.doCreateRenderPipelineTest(async, success, pipelineDescriptor);
});
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ Tests that you can not create a render pipeline with different per target blend
},
};
const isValid = cases[caseName](targets);
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() => t.device.createRenderPipeline(pipelineDescriptor),
!isValid
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ Tests @builtin(vertex_index) and @builtin(instance_index) each count as an attri
const numAttribs = t.device.limits.maxVertexAttributes - numAttribsToReserve;

const numBuiltinsUsed = (useVertexIndex ? 1 : 0) + (useInstanceIndex ? 1 : 0);
const isValid = numAttribs + numBuiltinsUsed <= t.device.limits.maxVertexAttributes;
const isValidInCompat = numAttribs + numBuiltinsUsed <= t.device.limits.maxVertexAttributes;
const isValidInCore = numAttribs <= t.device.limits.maxVertexAttributes;
const isValid = t.isCompatibility ? isValidInCompat : isValidInCore;

const inputs = range(numAttribs, i => `@location(${i}) v${i}: vec4f`);
const outputs = range(numAttribs, i => `v${i}`);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export const g = makeTestGroup(CompatibilityTest);
g.test('sample_mask')
.desc(`Tests that you can not create a shader module that uses sample_mask in compat mode.`)
.fn(t => {
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createShaderModule({
Expand Down Expand Up @@ -40,7 +40,7 @@ g.test('sample_mask')
g.test('sample_index')
.desc(`Tests that you can not create a shader module that uses sample_index in compat mode.`)
.fn(t => {
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createShaderModule({
Expand Down Expand Up @@ -77,7 +77,7 @@ g.test('interpolate')
.fn(t => {
const { interpolate, success } = t.params;

t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createShaderModule({
Expand Down Expand Up @@ -109,7 +109,7 @@ g.test('unsupportedStorageTextureFormats')
.fn(t => {
const { format } = t.params;

t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createShaderModule({
Expand Down Expand Up @@ -140,7 +140,7 @@ g.test('textureLoad_with_depth_textures')
const { type } = t.params;
const params = kDepthTextureTypeToParams[type];

t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createShaderModule({
Expand Down
14 changes: 7 additions & 7 deletions src/webgpu/compat/api/validation/texture/createTexture.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export const g = makeTestGroup(CompatibilityTest);
g.test('unsupportedTextureFormats')
.desc(`Tests that you can not create a bgra8unorm-srgb texture in compat mode.`)
.fn(t => {
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createTexture({
Expand All @@ -32,7 +32,7 @@ g.test('unsupportedTextureViewFormats')
`Tests that you can not create a bgra8unorm texture with a bgra8unorm-srgb viewFormat in compat mode.`
)
.fn(t => {
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createTexture({
Expand All @@ -56,9 +56,9 @@ g.test('invalidTextureBindingViewDimension')
)
.fn(t => {
const { dimension, textureBindingViewDimension } = t.params;
const depthOrArrayLayers = textureBindingViewDimension === '1d' || textureBindingViewDimension === '2d' ? 1 : 6;
const depthOrArrayLayers = dimension === '1d' || textureBindingViewDimension === '1d' || textureBindingViewDimension === '2d' ? 1 : 6;
const shouldError = getTextureDimensionFromView(textureBindingViewDimension) !== dimension;
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() => {
const texture = t.device.createTexture({
Expand Down Expand Up @@ -91,7 +91,7 @@ g.test('depthOrArrayLayers_incompatible_with_textureBindingViewDimension')
const shouldError =
(textureBindingViewDimension === '2d' && depthOrArrayLayers !== 1) ||
(textureBindingViewDimension === 'cube' && depthOrArrayLayers !== 6);
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() => {
const texture = t.device.createTexture({
Expand Down Expand Up @@ -138,7 +138,7 @@ g.test('format_reinterpretation')
{ format: info.baseFormat!, viewFormats: [format, info.baseFormat!] },
];
for (const { format, viewFormats } of formatPairs) {
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() => {
const texture = t.device.createTexture({
Expand All @@ -159,7 +159,7 @@ g.test('unsupportedStorageTextureFormats')
.params(u => u.combine('format', kCompatModeUnsupportedStorageTextureFormats))
.fn(t => {
const { format } = t.params;
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() =>
t.device.createTexture({
Expand Down
2 changes: 1 addition & 1 deletion src/webgpu/compat/api/validation/texture/cubeArray.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ g.test('cube_array')
});

const isValid = dimension === 'cube';
t.expectGPUError(
t.expectGPUErrorInCompatibilityMode(
'validation',
() => texture.createView({ dimension, format: 'rgba8unorm' }),
!isValid
Expand Down
25 changes: 22 additions & 3 deletions src/webgpu/compat/compatibility_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,27 @@ import { ValidationTest } from '../api/validation/validation_test.js';
export class CompatibilityTest extends ValidationTest {
override async init() {
await super.init();
if (!this.isCompatibility) {
this.skip('compatibility tests do not work on non-compatibility mode');
}
}

/**
* Expect a validation error inside the callback.
* except when not in compat mode.
*
* Tests should always do just one WebGPU call in the callback, to make sure that's what's tested.
*/
expectValidationErrorInCompatibilityMode(fn: () => void, shouldError: boolean = true): void {
this.expectValidationError(fn, this.isCompatibility && shouldError);
}

/**
* Expect the specified WebGPU error to be generated when running the provided function
* except when not in compat mode.
*/
expectGPUErrorInCompatibilityMode<R>(
filter: GPUErrorFilter,
fn: () => R,
shouldError: boolean = true
): R {
return this.expectGPUError(filter, fn, this.isCompatibility && shouldError);
}
}

0 comments on commit 5c23d90

Please sign in to comment.