|  | export const description = ` | 
|  | getBindGroupLayout validation tests. | 
|  | `; | 
|  |  | 
|  | import { AllFeaturesMaxLimitsGPUTest } from '../.././gpu_test.js'; | 
|  | import { makeTestGroup } from '../../../common/framework/test_group.js'; | 
|  | import { assert } from '../../../common/util/util.js'; | 
|  |  | 
|  | export const g = makeTestGroup(AllFeaturesMaxLimitsGPUTest); | 
|  |  | 
|  | g.test('index_range,explicit_layout') | 
|  | .desc( | 
|  | ` | 
|  | Test that a validation error is generated if the index is greater than the maximum number of bind | 
|  | groups. | 
|  | ` | 
|  | ) | 
|  | .params(u => u.combine('index', [0, 1, 2, 3, 4, 5])) | 
|  | .fn(t => { | 
|  | const { index } = t.params; | 
|  |  | 
|  | const pipelineBindGroupLayouts = t.device.createBindGroupLayout({ | 
|  | entries: [], | 
|  | }); | 
|  |  | 
|  | const pipelineLayout = t.device.createPipelineLayout({ | 
|  | bindGroupLayouts: [pipelineBindGroupLayouts], | 
|  | }); | 
|  |  | 
|  | const pipeline = t.device.createRenderPipeline({ | 
|  | layout: pipelineLayout, | 
|  | vertex: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @vertex | 
|  | fn main()-> @builtin(position) vec4<f32> { | 
|  | return vec4<f32>(0.0, 0.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | }, | 
|  | fragment: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @fragment | 
|  | fn main() -> @location(0) vec4<f32> { | 
|  | return vec4<f32>(0.0, 1.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | targets: [{ format: 'rgba8unorm' }], | 
|  | }, | 
|  | }); | 
|  |  | 
|  | const shouldError = index >= t.device.limits.maxBindGroups; | 
|  |  | 
|  | t.expectValidationError(() => { | 
|  | pipeline.getBindGroupLayout(index); | 
|  | }, shouldError); | 
|  | }); | 
|  |  | 
|  | g.test('index_range,auto_layout') | 
|  | .desc( | 
|  | ` | 
|  | Test that a validation error is generated if the index is greater than the maximum number of bind | 
|  | groups. | 
|  | ` | 
|  | ) | 
|  | .params(u => u.combine('index', [0, 1, 2, 3, 4, 5])) | 
|  | .fn(t => { | 
|  | const { index } = t.params; | 
|  |  | 
|  | const pipeline = t.device.createRenderPipeline({ | 
|  | layout: 'auto', | 
|  | vertex: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @vertex | 
|  | fn main()-> @builtin(position) vec4<f32> { | 
|  | return vec4<f32>(0.0, 0.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | }, | 
|  | fragment: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @group(0) @binding(0) var<uniform> binding: f32; | 
|  | @fragment | 
|  | fn main() -> @location(0) vec4<f32> { | 
|  | _ = binding; | 
|  | return vec4<f32>(0.0, 1.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | targets: [{ format: 'rgba8unorm' }], | 
|  | }, | 
|  | }); | 
|  |  | 
|  | const shouldError = index >= t.device.limits.maxBindGroups; | 
|  |  | 
|  | t.expectValidationError(() => { | 
|  | pipeline.getBindGroupLayout(index); | 
|  | }, shouldError); | 
|  | }); | 
|  |  | 
|  | g.test('unique_js_object,auto_layout') | 
|  | .desc( | 
|  | ` | 
|  | Test that getBindGroupLayout returns a new JavaScript object for each call. | 
|  | ` | 
|  | ) | 
|  | .fn(t => { | 
|  | const pipeline = t.device.createRenderPipeline({ | 
|  | layout: 'auto', | 
|  | vertex: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @vertex | 
|  | fn main()-> @builtin(position) vec4<f32> { | 
|  | return vec4<f32>(0.0, 0.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | }, | 
|  | fragment: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @group(0) @binding(0) var<uniform> binding: f32; | 
|  | @fragment | 
|  | fn main() -> @location(0) vec4<f32> { | 
|  | _ = binding; | 
|  | return vec4<f32>(0.0, 1.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | targets: [{ format: 'rgba8unorm' }], | 
|  | }, | 
|  | }); | 
|  |  | 
|  | const kIndex = 0; | 
|  | const bgl1 = pipeline.getBindGroupLayout(kIndex) as unknown as Record<string, number>; | 
|  | bgl1.extra = 42; | 
|  | const bgl2 = pipeline.getBindGroupLayout(kIndex) as unknown as Record<string, number>; | 
|  |  | 
|  | assert(bgl1 !== bgl2, 'objects are not the same object'); | 
|  | assert(bgl2.extra === undefined, 'objects do not retain expando properties'); | 
|  | }); | 
|  |  | 
|  | g.test('unique_js_object,explicit_layout') | 
|  | .desc( | 
|  | ` | 
|  | Test that getBindGroupLayout returns a new JavaScript object for each call. | 
|  | ` | 
|  | ) | 
|  | .fn(t => { | 
|  | const pipelineBindGroupLayouts = t.device.createBindGroupLayout({ | 
|  | entries: [], | 
|  | }); | 
|  |  | 
|  | const pipelineLayout = t.device.createPipelineLayout({ | 
|  | bindGroupLayouts: [pipelineBindGroupLayouts], | 
|  | }); | 
|  |  | 
|  | const pipeline = t.device.createRenderPipeline({ | 
|  | layout: pipelineLayout, | 
|  | vertex: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @vertex | 
|  | fn main()-> @builtin(position) vec4<f32> { | 
|  | return vec4<f32>(0.0, 0.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | }, | 
|  | fragment: { | 
|  | module: t.device.createShaderModule({ | 
|  | code: ` | 
|  | @fragment | 
|  | fn main() -> @location(0) vec4<f32> { | 
|  | return vec4<f32>(0.0, 1.0, 0.0, 1.0); | 
|  | }`, | 
|  | }), | 
|  | entryPoint: 'main', | 
|  | targets: [{ format: 'rgba8unorm' }], | 
|  | }, | 
|  | }); | 
|  |  | 
|  | const kIndex = 0; | 
|  | const bgl1 = pipeline.getBindGroupLayout(kIndex) as unknown as Record<string, number>; | 
|  | bgl1.extra = 42; | 
|  | const bgl2 = pipeline.getBindGroupLayout(kIndex) as unknown as Record<string, number>; | 
|  |  | 
|  | assert(bgl1 !== bgl2, 'objects are not the same object'); | 
|  | assert(bgl2.extra === undefined, 'objects do not retain expando properties'); | 
|  | }); |