@@ -6,6 +6,7 @@ TODO: review existing tests, write descriptions, and make sure tests are complet
6
6
7
7
import { makeTestGroup } from '../../../common/framework/test_group.js' ;
8
8
import { bufferBindingTypeInfo , kBufferBindingTypes } from '../../capability_info.js' ;
9
+ import { GPUConst } from '../../constants.js' ;
9
10
10
11
import { ValidationTest } from './validation_test.js' ;
11
12
@@ -162,3 +163,119 @@ g.test('bind_group_layouts,device_mismatch')
162
163
t . device . createPipelineLayout ( { bindGroupLayouts : [ layout0 , layout1 ] } ) ;
163
164
} , mismatched ) ;
164
165
} ) ;
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