Skip to content

Commit 566aba1

Browse files
Test GPUBuffer in GPUBindingResource (#4390)
* Test GPUBuffer in GPUBindingResource * Add more tests * Add operation test * Address feedback * Move test to a new file * Nit
1 parent 75289e0 commit 566aba1

3 files changed

Lines changed: 123 additions & 11 deletions

File tree

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
export const description = `
2+
Buffer tests in createBindGroup.
3+
`;
4+
5+
import { makeTestGroup } from '../../../../common/framework/test_group.js';
6+
import { AllFeaturesMaxLimitsGPUTest } from '../../../gpu_test.js';
7+
8+
export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest);
9+
10+
g.test('buffer_binding_resource')
11+
.desc(
12+
`Validate the correctness of the buffer binding resource by filling the buffer with
13+
testable data, clearing buffer in shader, and verifying the content of the whole buffer:
14+
- covers the whole buffer
15+
- covers the beginning of the buffer
16+
- covers the end of the buffer
17+
- covers neither the beginning nor the end of the buffer`
18+
)
19+
.paramsSubcasesOnly(u =>
20+
u //
21+
.combine('bindBufferResource', [false, true] as const)
22+
.combine('offset', [0, 256, undefined])
23+
.combine('size', [4, 8, undefined])
24+
.combine('extraBufferSize', [0, 8])
25+
// offset and size don't matter if bindBufferResource is true
26+
.filter(p => !p.bindBufferResource || (p.offset === undefined && p.size === undefined))
27+
)
28+
.fn(t => {
29+
const { bindBufferResource, offset, size, extraBufferSize } = t.params;
30+
31+
const bufferSize = (offset ?? 0) + (size ?? 16) + extraBufferSize;
32+
const bufferData = new Uint8Array(bufferSize);
33+
for (let i = 0; i < bufferSize; ++i) {
34+
bufferData[i] = i + 1;
35+
}
36+
37+
const buffer = t.makeBufferWithContents(
38+
bufferData,
39+
GPUBufferUsage.COPY_DST | GPUBufferUsage.COPY_SRC | GPUBufferUsage.STORAGE
40+
);
41+
42+
const pipeline = t.device.createComputePipeline({
43+
layout: 'auto',
44+
compute: {
45+
module: t.device.createShaderModule({
46+
code: `
47+
@group(0) @binding(0) var<storage, read_write> buffer : array<u32>;
48+
49+
@compute @workgroup_size(1) fn main() {
50+
for (var i = 0u; i < arrayLength(&buffer); i = i + 1u) {
51+
buffer[i] = 0;
52+
}
53+
return;
54+
}`,
55+
}),
56+
},
57+
});
58+
59+
const resource = bindBufferResource ? buffer : { buffer, offset, size };
60+
const bg = t.device.createBindGroup({
61+
entries: [{ binding: 0, resource }],
62+
layout: pipeline.getBindGroupLayout(0),
63+
});
64+
65+
const encoder = t.device.createCommandEncoder();
66+
const pass = encoder.beginComputePass();
67+
pass.setPipeline(pipeline);
68+
pass.setBindGroup(0, bg);
69+
pass.dispatchWorkgroups(1);
70+
pass.end();
71+
t.device.queue.submit([encoder.finish()]);
72+
73+
const expectOffset = bindBufferResource ? 0 : offset ?? 0;
74+
const expectSize = bindBufferResource ? bufferSize : size ?? bufferSize - expectOffset;
75+
76+
for (let i = 0; i < expectSize; ++i) {
77+
bufferData[expectOffset + i] = 0;
78+
}
79+
80+
t.expectGPUBufferValuesEqual(buffer, bufferData);
81+
});

src/webgpu/api/operation/resource_init/buffer.spec.ts

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,32 @@ class F extends AllFeaturesMaxLimitsGPUTest {
4848
buffer: GPUBuffer,
4949
bufferOffset: number,
5050
boundBufferSize: number
51+
): void {
52+
this.TestBufferZeroInitInBindGroupInternal(
53+
computeShaderModule,
54+
buffer,
55+
false,
56+
bufferOffset,
57+
boundBufferSize
58+
);
59+
const bindBufferResource = bufferOffset === 0 && boundBufferSize === buffer.size;
60+
if (bindBufferResource) {
61+
this.TestBufferZeroInitInBindGroupInternal(
62+
computeShaderModule,
63+
buffer,
64+
true,
65+
bufferOffset,
66+
boundBufferSize
67+
);
68+
}
69+
}
70+
71+
TestBufferZeroInitInBindGroupInternal(
72+
computeShaderModule: GPUShaderModule,
73+
buffer: GPUBuffer,
74+
bindBufferResource: boolean,
75+
bufferOffset: number,
76+
boundBufferSize: number
5177
): void {
5278
const computePipeline = this.device.createComputePipeline({
5379
layout: 'auto',
@@ -61,16 +87,19 @@ class F extends AllFeaturesMaxLimitsGPUTest {
6187
size: [1, 1, 1],
6288
usage: GPUTextureUsage.COPY_SRC | GPUTextureUsage.STORAGE_BINDING,
6389
});
90+
const resource = bindBufferResource
91+
? buffer
92+
: {
93+
buffer,
94+
offset: bufferOffset,
95+
size: boundBufferSize,
96+
};
6497
const bindGroup = this.device.createBindGroup({
6598
layout: computePipeline.getBindGroupLayout(0),
6699
entries: [
67100
{
68101
binding: 0,
69-
resource: {
70-
buffer,
71-
offset: bufferOffset,
72-
size: boundBufferSize,
73-
},
102+
resource,
74103
},
75104
{
76105
binding: 1,

src/webgpu/api/validation/createBindGroup.spec.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -446,6 +446,7 @@ g.test('buffer_offset_and_size_for_bind_groups_match')
446446
.paramsSubcasesOnly([
447447
{ offset: 0, size: 512, _success: true }, // offset 0 is valid
448448
{ offset: 256, size: 256, _success: true }, // offset 256 (aligned) is valid
449+
{ bindBufferResource: true, _success: true }, // full buffer is valid
449450

450451
// Touching the end of the buffer
451452
{ offset: 0, size: 1024, _success: true },
@@ -471,7 +472,7 @@ g.test('buffer_offset_and_size_for_bind_groups_match')
471472
{ offset: 1024, size: 1, _success: false }, // offset+size is OOB
472473
])
473474
.fn(t => {
474-
const { offset, size, _success } = t.params;
475+
const { bindBufferResource, offset, size, _success } = t.params;
475476

476477
const bindGroupLayout = t.device.createBindGroupLayout({
477478
entries: [{ binding: 0, visibility: GPUShaderStage.COMPUTE, buffer: { type: 'storage' } }],
@@ -482,11 +483,12 @@ g.test('buffer_offset_and_size_for_bind_groups_match')
482483
usage: GPUBufferUsage.STORAGE,
483484
});
484485

486+
const resource = bindBufferResource ? buffer : { buffer, offset, size };
485487
const descriptor = {
486488
entries: [
487489
{
488490
binding: 0,
489-
resource: { buffer, offset, size },
491+
resource,
490492
},
491493
],
492494
layout: bindGroupLayout,
@@ -561,9 +563,10 @@ g.test('buffer,resource_state')
561563
.combine('state', kResourceStates)
562564
.combine('entry', bufferBindingEntries(true))
563565
.combine('visibilityMask', [kAllShaderStages, GPUConst.ShaderStage.COMPUTE] as const)
566+
.combine('bindBufferResource', [false, true] as const)
564567
)
565568
.fn(t => {
566-
const { state, entry, visibilityMask } = t.params;
569+
const { state, entry, visibilityMask, bindBufferResource } = t.params;
567570

568571
assert(entry.buffer !== undefined);
569572
const info = bufferBindingTypeInfo(entry.buffer);
@@ -586,15 +589,14 @@ g.test('buffer,resource_state')
586589
size: 4,
587590
});
588591

592+
const resource = bindBufferResource ? buffer : { buffer };
589593
t.expectValidationError(() => {
590594
t.device.createBindGroup({
591595
layout: bgl,
592596
entries: [
593597
{
594598
binding: 0,
595-
resource: {
596-
buffer,
597-
},
599+
resource,
598600
},
599601
],
600602
});

0 commit comments

Comments
 (0)