Skip to content

Commit

Permalink
Compat: skip memory_sync buffer tests when no support
Browse files Browse the repository at this point in the history
At a glance I doesn't seem like there is anything to
refactor here. The test that are actually using storage
buffers need storage buffers. So, skip them if there are none.
  • Loading branch information
greggman committed Dec 17, 2024
1 parent 64c1fa9 commit 15b739a
Show file tree
Hide file tree
Showing 3 changed files with 101 additions and 2 deletions.
49 changes: 49 additions & 0 deletions src/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,21 @@ export function checkOpsValidForContext(
return true;
}

function readOpUsesStorageBufferInFragmentShader(readOp: ReadOp) {
return (
readOp === 'storage-read' ||
readOp === 'input-vertex' ||
readOp === 'input-index' ||
readOp === 'input-indirect' ||
readOp === 'input-indirect-index' ||
readOp === 'constant-uniform'
);
}

function writeOpUsesStorageBufferInFragmentShader(writeOp: WriteOp) {
return writeOp === 'storage' || writeOp === 'write-buffer';
}

const kDummyVertexShader = `
@vertex fn vert_main() -> @builtin(position) vec4<f32> {
return vec4<f32>(0.5, 0.5, 0.0, 1.0);
Expand All @@ -145,6 +160,40 @@ export class BufferSyncTest extends GPUTest {
tmpValueBuffers: (GPUBuffer | undefined)[] = [undefined, undefined];
tmpValueTextures: (GPUTexture | undefined)[] = [undefined, undefined];

skipIfNoSupportForStorageBuffersInFragmentStage() {
if (this.isCompatibility) {
this.skipIf(
!(this.device.limits.maxStorageBuffersInFragmentStage! >= 2),
`maxStorageBuffersInFragmentStage(${this.device.limits.maxStorageBuffersInFragmentStage}) < 2`
);
}
}

skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
readOp: ReadOp | readonly ReadOp[],
writeOp: WriteOp | readonly WriteOp[]
) {
if (this.isCompatibility) {
const readOps = Array.isArray(readOp) ? readOp : [readOp];
const writeOps = Array.isArray(writeOp) ? writeOp : [writeOp];
const readOpsUseStorageBuffersInFragmentStage = readOps.reduce(
(uses, op) => uses || readOpUsesStorageBufferInFragmentShader(op),
false
);
const writeOpsUseStorageBuffersInFragmentStage = writeOps.reduce(
(uses, op) => uses || writeOpUsesStorageBufferInFragmentShader(op),
false
);
const usesStorageBuffersInFragmentStage =
readOpsUseStorageBuffersInFragmentStage || writeOpsUseStorageBuffersInFragmentStage;
this.skipIf(
usesStorageBuffersInFragmentStage &&
!(this.device.limits.maxStorageBuffersInFragmentStage! >= 2),
`maxStorageBuffersInFragmentStage(${this.device.limits.maxStorageBuffersInFragmentStage}) < 2`
);
}
}

// These intermediate buffers/textures are created before any read/write op
// to avoid extra memory synchronization between ops introduced by await on buffer/texture creations.
// Create extra buffers/textures needed by write operation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ TODO: Tests with more than one buffer to try to stress implementations a little
`;

import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { MaxLimitsTestMixin } from '../../../../gpu_test.js';
import {
kOperationBoundaries,
kBoundaryInfo,
Expand All @@ -34,7 +35,7 @@ const kSrcValue = 0;
// The op value is what the read/write operation write into the target buffer.
const kOpValue = 1;

export const g = makeTestGroup(BufferSyncTest);
export const g = makeTestGroup(MaxLimitsTestMixin(BufferSyncTest));

g.test('rw')
.desc(
Expand Down Expand Up @@ -66,6 +67,12 @@ g.test('rw')
)
.fn(async t => {
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
readOp,
writeOp
);

const helper = new OperationContextHelper(t);

const srcBuffers: GPUBuffer[] = [];
Expand Down Expand Up @@ -131,6 +138,12 @@ g.test('wr')
)
.fn(async t => {
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
readOp,
writeOp
);

const helper = new OperationContextHelper(t);

const srcBuffers: GPUBuffer[] = [];
Expand Down Expand Up @@ -196,6 +209,12 @@ g.test('ww')
)
.fn(async t => {
const { writeOps, contexts, boundary } = t.params;

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
[],
writeOps
);

const helper = new OperationContextHelper(t);

const buffers: GPUBuffer[] = [];
Expand Down Expand Up @@ -245,6 +264,8 @@ g.test('multiple_pairs_of_draws_in_one_render_pass')
.fn(async t => {
const { firstDrawUseBundle, secondDrawUseBundle } = t.params;

t.skipIfNoSupportForStorageBuffersInFragmentStage();

const encoder = t.device.createCommandEncoder();
const passEncoder = t.beginSimpleRenderPass(encoder);

Expand Down Expand Up @@ -294,6 +315,8 @@ g.test('multiple_pairs_of_draws_in_one_render_bundle')
colorFormats: ['rgba8unorm'],
});

t.skipIfNoSupportForStorageBuffersInFragmentStage();

const kBufferCount = 4;
const buffers: GPUBuffer[] = [];
for (let b = 0; b < kBufferCount; ++b) {
Expand Down Expand Up @@ -327,6 +350,8 @@ g.test('multiple_pairs_of_dispatches_in_one_compute_pass')
`
)
.fn(async t => {
t.skipIfNoSupportForStorageBuffersInFragmentStage();

const encoder = t.device.createCommandEncoder();
const pass = encoder.beginComputePass();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ Wait on another fence, then call expectContents to verify the dst buffer value.
`;

import { makeTestGroup } from '../../../../../common/framework/test_group.js';
import { MaxLimitsTestMixin } from '../../../../gpu_test.js';
import {
kOperationBoundaries,
kBoundaryInfo,
Expand All @@ -32,7 +33,7 @@ const kSrcValue = 0;
// The op value is what the read/write operation write into the target buffer.
const kOpValue = 1;

export const g = makeTestGroup(BufferSyncTest);
export const g = makeTestGroup(MaxLimitsTestMixin(BufferSyncTest));

g.test('rw')
.desc(
Expand Down Expand Up @@ -65,6 +66,11 @@ g.test('rw')
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
const helper = new OperationContextHelper(t);

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
readOp,
writeOp
);

const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);

Expand Down Expand Up @@ -108,6 +114,12 @@ g.test('wr')
)
.fn(async t => {
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
readOp,
writeOp
);

const helper = new OperationContextHelper(t);

const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
Expand Down Expand Up @@ -151,6 +163,12 @@ g.test('ww')
)
.fn(async t => {
const { writeOps, contexts, boundary } = t.params;

t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
[],
writeOps
);

const helper = new OperationContextHelper(t);

const buffer = await t.createBufferWithValue(0);
Expand Down Expand Up @@ -178,7 +196,10 @@ g.test('two_draws_in_the_same_render_pass')
.combine('secondDrawUseBundle', [false, true])
)
.fn(async t => {
t.skipIfNoSupportForStorageBuffersInFragmentStage();

const { firstDrawUseBundle, secondDrawUseBundle } = t.params;

const buffer = await t.createBufferWithValue(0);
const encoder = t.device.createCommandEncoder();
const passEncoder = t.beginSimpleRenderPass(encoder);
Expand Down Expand Up @@ -211,6 +232,8 @@ g.test('two_draws_in_the_same_render_bundle')
data in buffer is either 1 or 2.`
)
.fn(async t => {
t.skipIfNoSupportForStorageBuffersInFragmentStage();

const buffer = await t.createBufferWithValue(0);
const encoder = t.device.createCommandEncoder();
const passEncoder = t.beginSimpleRenderPass(encoder);
Expand Down Expand Up @@ -239,6 +262,8 @@ g.test('two_dispatches_in_the_same_compute_pass')
data in buffer is 2.`
)
.fn(async t => {
t.skipIfNoSupportForStorageBuffersInFragmentStage();

const buffer = await t.createBufferWithValue(0);
const encoder = t.device.createCommandEncoder();
const pass = encoder.beginComputePass();
Expand Down

0 comments on commit 15b739a

Please sign in to comment.