| 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'); |
| }); |