1export const description = ` 2createPipelineLayout validation tests. 3`; 4 5import { poptions, params } from '../../../common/framework/params_builder.js'; 6import { makeTestGroup } from '../../../common/framework/test_group.js'; 7import { kBindingTypeInfo } from '../../capability_info.js'; 8 9import { ValidationTest } from './validation_test.js'; 10 11function clone<T extends GPUBindGroupLayoutDescriptor>(descriptor: T): T { 12 return JSON.parse(JSON.stringify(descriptor)); 13} 14 15export const g = makeTestGroup(ValidationTest); 16 17g.test('number_of_dynamic_buffers_exceeds_the_maximum_value') 18 .params( 19 params() 20 .combine(poptions('visibility', [0, 2, 4, 6])) 21 .combine( 22 poptions('type', ['uniform-buffer', 'storage-buffer', 'readonly-storage-buffer'] as const) 23 ) 24 ) 25 .fn(async t => { 26 const { type, visibility } = t.params; 27 const { maxDynamic } = kBindingTypeInfo[type].perPipelineLimitClass; 28 29 const maxDynamicBufferBindings: GPUBindGroupLayoutEntry[] = []; 30 for (let binding = 0; binding < maxDynamic; binding++) { 31 maxDynamicBufferBindings.push({ binding, visibility, type, hasDynamicOffset: true }); 32 } 33 34 const maxDynamicBufferBindGroupLayout = t.device.createBindGroupLayout({ 35 entries: maxDynamicBufferBindings, 36 }); 37 38 const goodDescriptor = { 39 entries: [{ binding: 0, visibility, type, hasDynamicOffset: false }], 40 }; 41 42 const goodPipelineLayoutDescriptor = { 43 bindGroupLayouts: [ 44 maxDynamicBufferBindGroupLayout, 45 t.device.createBindGroupLayout(goodDescriptor), 46 ], 47 }; 48 49 // Control case 50 t.device.createPipelineLayout(goodPipelineLayoutDescriptor); 51 52 // Check dynamic buffers exceed maximum in pipeline layout. 53 const badDescriptor = clone(goodDescriptor); 54 badDescriptor.entries[0].hasDynamicOffset = true; 55 56 const badPipelineLayoutDescriptor = { 57 bindGroupLayouts: [ 58 maxDynamicBufferBindGroupLayout, 59 t.device.createBindGroupLayout(badDescriptor), 60 ], 61 }; 62 63 t.expectValidationError(() => { 64 t.device.createPipelineLayout(badPipelineLayoutDescriptor); 65 }); 66 }); 67 68g.test('number_of_bind_group_layouts_exceeds_the_maximum_value').fn(async t => { 69 const bindGroupLayoutDescriptor: GPUBindGroupLayoutDescriptor = { 70 entries: [], 71 }; 72 73 // 4 is the maximum number of bind group layouts. 74 const maxBindGroupLayouts = [1, 2, 3, 4].map(() => 75 t.device.createBindGroupLayout(bindGroupLayoutDescriptor) 76 ); 77 78 const goodPipelineLayoutDescriptor = { 79 bindGroupLayouts: maxBindGroupLayouts, 80 }; 81 82 // Control case 83 t.device.createPipelineLayout(goodPipelineLayoutDescriptor); 84 85 // Check bind group layouts exceed maximum in pipeline layout. 86 const badPipelineLayoutDescriptor = { 87 bindGroupLayouts: [ 88 ...maxBindGroupLayouts, 89 t.device.createBindGroupLayout(bindGroupLayoutDescriptor), 90 ], 91 }; 92 93 t.expectValidationError(() => { 94 t.device.createPipelineLayout(badPipelineLayoutDescriptor); 95 }); 96}); 97