Skip to content

Commit 8be4ce7

Browse files
authored
Compat: skip memory_sync buffer tests when no support (gpuweb#4101)
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.
1 parent 3c73a4b commit 8be4ce7

File tree

3 files changed

+101
-2
lines changed

3 files changed

+101
-2
lines changed

src/webgpu/api/operation/memory_sync/buffer/buffer_sync_test.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,21 @@ export function checkOpsValidForContext(
127127
return true;
128128
}
129129

130+
function readOpUsesStorageBufferInFragmentShader(readOp: ReadOp) {
131+
return (
132+
readOp === 'storage-read' ||
133+
readOp === 'input-vertex' ||
134+
readOp === 'input-index' ||
135+
readOp === 'input-indirect' ||
136+
readOp === 'input-indirect-index' ||
137+
readOp === 'constant-uniform'
138+
);
139+
}
140+
141+
function writeOpUsesStorageBufferInFragmentShader(writeOp: WriteOp) {
142+
return writeOp === 'storage' || writeOp === 'write-buffer';
143+
}
144+
130145
const kDummyVertexShader = `
131146
@vertex fn vert_main() -> @builtin(position) vec4<f32> {
132147
return vec4<f32>(0.5, 0.5, 0.0, 1.0);
@@ -145,6 +160,40 @@ export class BufferSyncTest extends GPUTest {
145160
tmpValueBuffers: (GPUBuffer | undefined)[] = [undefined, undefined];
146161
tmpValueTextures: (GPUTexture | undefined)[] = [undefined, undefined];
147162

163+
skipIfNoSupportForStorageBuffersInFragmentStage() {
164+
if (this.isCompatibility) {
165+
this.skipIf(
166+
!(this.device.limits.maxStorageBuffersInFragmentStage! >= 2),
167+
`maxStorageBuffersInFragmentStage(${this.device.limits.maxStorageBuffersInFragmentStage}) < 2`
168+
);
169+
}
170+
}
171+
172+
skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
173+
readOp: ReadOp | readonly ReadOp[],
174+
writeOp: WriteOp | readonly WriteOp[]
175+
) {
176+
if (this.isCompatibility) {
177+
const readOps = Array.isArray(readOp) ? readOp : [readOp];
178+
const writeOps = Array.isArray(writeOp) ? writeOp : [writeOp];
179+
const readOpsUseStorageBuffersInFragmentStage = readOps.reduce(
180+
(uses, op) => uses || readOpUsesStorageBufferInFragmentShader(op),
181+
false
182+
);
183+
const writeOpsUseStorageBuffersInFragmentStage = writeOps.reduce(
184+
(uses, op) => uses || writeOpUsesStorageBufferInFragmentShader(op),
185+
false
186+
);
187+
const usesStorageBuffersInFragmentStage =
188+
readOpsUseStorageBuffersInFragmentStage || writeOpsUseStorageBuffersInFragmentStage;
189+
this.skipIf(
190+
usesStorageBuffersInFragmentStage &&
191+
!(this.device.limits.maxStorageBuffersInFragmentStage! >= 2),
192+
`maxStorageBuffersInFragmentStage(${this.device.limits.maxStorageBuffersInFragmentStage}) < 2`
193+
);
194+
}
195+
}
196+
148197
// These intermediate buffers/textures are created before any read/write op
149198
// to avoid extra memory synchronization between ops introduced by await on buffer/texture creations.
150199
// Create extra buffers/textures needed by write operation

src/webgpu/api/operation/memory_sync/buffer/multiple_buffers.spec.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ TODO: Tests with more than one buffer to try to stress implementations a little
1616
`;
1717

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

37-
export const g = makeTestGroup(BufferSyncTest);
38+
export const g = makeTestGroup(MaxLimitsTestMixin(BufferSyncTest));
3839

3940
g.test('rw')
4041
.desc(
@@ -66,6 +67,12 @@ g.test('rw')
6667
)
6768
.fn(async t => {
6869
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
70+
71+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
72+
readOp,
73+
writeOp
74+
);
75+
6976
const helper = new OperationContextHelper(t);
7077

7178
const srcBuffers: GPUBuffer[] = [];
@@ -131,6 +138,12 @@ g.test('wr')
131138
)
132139
.fn(async t => {
133140
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
141+
142+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
143+
readOp,
144+
writeOp
145+
);
146+
134147
const helper = new OperationContextHelper(t);
135148

136149
const srcBuffers: GPUBuffer[] = [];
@@ -196,6 +209,12 @@ g.test('ww')
196209
)
197210
.fn(async t => {
198211
const { writeOps, contexts, boundary } = t.params;
212+
213+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
214+
[],
215+
writeOps
216+
);
217+
199218
const helper = new OperationContextHelper(t);
200219

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

267+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
268+
248269
const encoder = t.device.createCommandEncoder();
249270
const passEncoder = t.beginSimpleRenderPass(encoder);
250271

@@ -294,6 +315,8 @@ g.test('multiple_pairs_of_draws_in_one_render_bundle')
294315
colorFormats: ['rgba8unorm'],
295316
});
296317

318+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
319+
297320
const kBufferCount = 4;
298321
const buffers: GPUBuffer[] = [];
299322
for (let b = 0; b < kBufferCount; ++b) {
@@ -327,6 +350,8 @@ g.test('multiple_pairs_of_dispatches_in_one_compute_pass')
327350
`
328351
)
329352
.fn(async t => {
353+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
354+
330355
const encoder = t.device.createCommandEncoder();
331356
const pass = encoder.beginComputePass();
332357

src/webgpu/api/operation/memory_sync/buffer/single_buffer.spec.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Wait on another fence, then call expectContents to verify the dst buffer value.
1414
`;
1515

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

35-
export const g = makeTestGroup(BufferSyncTest);
36+
export const g = makeTestGroup(MaxLimitsTestMixin(BufferSyncTest));
3637

3738
g.test('rw')
3839
.desc(
@@ -65,6 +66,11 @@ g.test('rw')
6566
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
6667
const helper = new OperationContextHelper(t);
6768

69+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
70+
readOp,
71+
writeOp
72+
);
73+
6874
const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
6975
await t.createIntermediateBuffersAndTexturesForWriteOp(writeOp, 0, kOpValue);
7076

@@ -108,6 +114,12 @@ g.test('wr')
108114
)
109115
.fn(async t => {
110116
const { readContext, readOp, writeContext, writeOp, boundary } = t.params;
117+
118+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
119+
readOp,
120+
writeOp
121+
);
122+
111123
const helper = new OperationContextHelper(t);
112124

113125
const { srcBuffer, dstBuffer } = await t.createBuffersForReadOp(readOp, kSrcValue, kOpValue);
@@ -151,6 +163,12 @@ g.test('ww')
151163
)
152164
.fn(async t => {
153165
const { writeOps, contexts, boundary } = t.params;
166+
167+
t.skipIfReadOpsOrWriteOpsUsesStorageBufferInFragmentStageAndNoSupportStorageBuffersInFragmentShaders(
168+
[],
169+
writeOps
170+
);
171+
154172
const helper = new OperationContextHelper(t);
155173

156174
const buffer = await t.createBufferWithValue(0);
@@ -178,7 +196,10 @@ g.test('two_draws_in_the_same_render_pass')
178196
.combine('secondDrawUseBundle', [false, true])
179197
)
180198
.fn(async t => {
199+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
200+
181201
const { firstDrawUseBundle, secondDrawUseBundle } = t.params;
202+
182203
const buffer = await t.createBufferWithValue(0);
183204
const encoder = t.device.createCommandEncoder();
184205
const passEncoder = t.beginSimpleRenderPass(encoder);
@@ -211,6 +232,8 @@ g.test('two_draws_in_the_same_render_bundle')
211232
data in buffer is either 1 or 2.`
212233
)
213234
.fn(async t => {
235+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
236+
214237
const buffer = await t.createBufferWithValue(0);
215238
const encoder = t.device.createCommandEncoder();
216239
const passEncoder = t.beginSimpleRenderPass(encoder);
@@ -239,6 +262,8 @@ g.test('two_dispatches_in_the_same_compute_pass')
239262
data in buffer is 2.`
240263
)
241264
.fn(async t => {
265+
t.skipIfNoSupportForStorageBuffersInFragmentStage();
266+
242267
const buffer = await t.createBufferWithValue(0);
243268
const encoder = t.device.createCommandEncoder();
244269
const pass = encoder.beginComputePass();

0 commit comments

Comments
 (0)