Skip to content

Commit c2071c1

Browse files
committed
Add validation tests on the creation of pipeline layout with null bind group layout
1 parent 096f9fd commit c2071c1

File tree

1 file changed

+117
-0
lines changed

1 file changed

+117
-0
lines changed

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

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ TODO: review existing tests, write descriptions, and make sure tests are complet
66

77
import { makeTestGroup } from '../../../common/framework/test_group.js';
88
import { bufferBindingTypeInfo, kBufferBindingTypes } from '../../capability_info.js';
9+
import { GPUConst } from '../../constants.js';
910

1011
import { ValidationTest } from './validation_test.js';
1112

@@ -162,3 +163,119 @@ g.test('bind_group_layouts,device_mismatch')
162163
t.device.createPipelineLayout({ bindGroupLayouts: [layout0, layout1] });
163164
}, mismatched);
164165
});
166+
167+
const MaybeNullBindGroupLayoutTypes = ['Null', 'Empty', 'NonEmpty'] as const;
168+
169+
g.test('bind_group_layouts,null_bind_group_layouts')
170+
.desc(
171+
`
172+
Tests that it is valid to create a pipeline layout with null bind group layouts.
173+
`
174+
)
175+
.paramsSubcasesOnly(u =>
176+
u //
177+
.combine('bindGroupLayoutCount', [1, 2, 3, 4] as const)
178+
.combine('bindGroupLayout0', MaybeNullBindGroupLayoutTypes)
179+
.combine('bindGroupLayout1', MaybeNullBindGroupLayoutTypes)
180+
.combine('bindGroupLayout2', MaybeNullBindGroupLayoutTypes)
181+
.combine('bindGroupLayout3', MaybeNullBindGroupLayoutTypes)
182+
.filter(t => {
183+
switch (t.bindGroupLayoutCount) {
184+
case 1:
185+
// Only bindGroupLayout0 is valid and represents null bind group layout, and we don't
186+
// need to care about the other bind group layouts.
187+
return (
188+
t.bindGroupLayout0 === 'Null' &&
189+
t.bindGroupLayout1 === 'Null' &&
190+
t.bindGroupLayout2 === 'Null' &&
191+
t.bindGroupLayout3 === 'Null'
192+
);
193+
case 2:
194+
// Only bindGroupLayout0 and bindGroupLayout1 are valid and at least one of them
195+
// represents null bind group layout, and we don't need to care about the other bind
196+
// group layouts.
197+
return (
198+
(t.bindGroupLayout0 === 'Null' || t.bindGroupLayout1 === 'Null') &&
199+
t.bindGroupLayout2 === 'Null' &&
200+
t.bindGroupLayout3 === 'Null'
201+
);
202+
case 3:
203+
// Only bindGroupLayout0, bindGroupLayout1 and bindGroupLayout2 are valid and at least
204+
// one of them represents null bind group layout, and we don't need to care about
205+
// bindGroupLayout3.
206+
return (
207+
(t.bindGroupLayout0 === 'Null' ||
208+
t.bindGroupLayout1 === 'Null' ||
209+
t.bindGroupLayout2 === 'Null') &&
210+
t.bindGroupLayout3 === 'Null'
211+
);
212+
case 4:
213+
// At lease one of the bindGroupLayout0, bindGroupLayout1, bindGroupLayout2 and
214+
// bindGroupLayout3 represents null bind group layout.
215+
return (
216+
t.bindGroupLayout0 === 'Null' ||
217+
t.bindGroupLayout1 === 'Null' ||
218+
t.bindGroupLayout2 === 'Null' ||
219+
t.bindGroupLayout3 === 'Null'
220+
);
221+
default:
222+
return false;
223+
}
224+
})
225+
)
226+
.fn(t => {
227+
const {
228+
bindGroupLayoutCount,
229+
bindGroupLayout0,
230+
bindGroupLayout1,
231+
bindGroupLayout2,
232+
bindGroupLayout3,
233+
} = t.params;
234+
235+
const emptyBindGroupLayout = t.device.createBindGroupLayout({
236+
entries: [],
237+
});
238+
const nonEmptyBindGroupLayout = t.device.createBindGroupLayout({
239+
entries: [
240+
{
241+
binding: 0,
242+
visibility: GPUConst.ShaderStage.COMPUTE,
243+
texture: {},
244+
},
245+
],
246+
});
247+
248+
const bindGroupLayouts: (GPUBindGroupLayout | null)[] = [];
249+
250+
const AddBindGroupLayout = function (
251+
bindGroupLayoutType: (typeof MaybeNullBindGroupLayoutTypes)[number]
252+
) {
253+
switch (bindGroupLayoutType) {
254+
case 'Null':
255+
bindGroupLayouts.push(null);
256+
break;
257+
case 'Empty':
258+
bindGroupLayouts.push(emptyBindGroupLayout);
259+
break;
260+
case 'NonEmpty':
261+
bindGroupLayouts.push(nonEmptyBindGroupLayout);
262+
break;
263+
}
264+
};
265+
266+
AddBindGroupLayout(bindGroupLayout0);
267+
if (bindGroupLayoutCount > 1) {
268+
AddBindGroupLayout(bindGroupLayout1);
269+
}
270+
if (bindGroupLayoutCount > 2) {
271+
AddBindGroupLayout(bindGroupLayout2);
272+
}
273+
if (bindGroupLayoutCount > 3) {
274+
AddBindGroupLayout(bindGroupLayout3);
275+
}
276+
277+
const kShouldError = false;
278+
t.expectValidationError(() => {
279+
t.device.createPipelineLayout({ bindGroupLayouts });
280+
}, kShouldError);
281+
});

0 commit comments

Comments
 (0)