diff --git a/src/data-definitions.ts b/src/data-definitions.ts index 0eb2b42..5b0108d 100644 --- a/src/data-definitions.ts +++ b/src/data-definitions.ts @@ -173,7 +173,13 @@ export function makeBindGroupLayoutDescriptors( visibility: resource.entry.visibility | (entry?.visibility || 0), }); } - return bindGroupLayoutDescriptorsByGroupByBinding.map(v => ({entries: [...v.values()].sort(byBinding) })); + const descriptors = bindGroupLayoutDescriptorsByGroupByBinding.map(v => ({entries: [...v.values()].sort(byBinding) })); + for (let i = 0; i < descriptors.length; ++i) { + if (!descriptors[i]) { + descriptors[i] = { entries: [] }; + } + } + return descriptors; } function getNamedVariables(reflect: WgslReflect, variables: VariableInfo[]): VariableDefinitions { diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..e69de29 diff --git a/test/tests/data-definition-test.js b/test/tests/data-definition-test.js index d492887..013ff71 100644 --- a/test/tests/data-definition-test.js +++ b/test/tests/data-definition-test.js @@ -655,7 +655,9 @@ describe('data-definition-tests', () => { }, ], }, - undefined, + { + entries: [], + }, { entries: [ { @@ -737,7 +739,7 @@ describe('data-definition-tests', () => { assertDeepEqual(layouts, expected); }); - it('handles merges stages', () => { + it('handles merged stages', () => { const code = ` @group(0) @binding(1) var tex2d: texture_2d; @group(0) @binding(2) var samp: sampler; @@ -785,6 +787,127 @@ describe('data-definition-tests', () => { assertDeepEqual(layouts, expected); }); + it('handles empty groups', () => { + const code = ` + @group(3) @binding(1) var u: vec4f; + @compute fn cs() { + _ = u; + } + `; + const d = makeShaderDataDefinitions(code); + const layouts = makeBindGroupLayoutDescriptors(d, { + compute: { + entryPoint: 'cs', + }, + }); + const expected = [ + { + entries: [], + }, + { + entries: [], + }, + { + entries: [], + }, + { + entries: [ + { + binding: 1, + visibility: 4, + buffer: { + }, + }, + ], + }, + ]; + assertDeepEqual(layouts, expected); + }); + + it('handles unnamed entrypoints', () => { + const code = ` + @group(0) @binding(1) var tex2d: texture_2d; + @group(0) @binding(2) var samp: sampler; + @group(0) @binding(3) var u1: vec4f; + @group(0) @binding(4) var u2: vec4f; + @vertex fn vs() -> @builtin(position) vec4f { + _ = tex2d; + _ = samp; + _ = u1; + } + @fragment fn fs() -> @location(0) vec4f { + _ = tex2d; + _ = samp; + return vec4f(0); + } + @compute fn cs() { + _ = u1; + _ = u2; + } + + `; + const d = makeShaderDataDefinitions(code); + { + const layouts = makeBindGroupLayoutDescriptors(d, { + compute: { }, + }); + const expected = [ + { + entries: [ + { + binding: 3, + visibility: 4, + buffer: { + }, + }, + { + binding: 4, + visibility: 4, + buffer: { + }, + }, + ], + }, + ]; + assertDeepEqual(layouts, expected); + } + { + const layouts = makeBindGroupLayoutDescriptors(d, { + vertex: { }, + fragment: { }, + }); + const expected = [ + { + entries: [ + { + binding: 1, + visibility: 3, + texture: { + sampleType: 'float', + viewDimension: '2d', + multisampled: false, + }, + }, + { + binding: 2, + visibility: 3, + sampler: { + type: 'filtering', + }, + }, + { + binding: 3, + visibility: 1, + buffer: { + }, + }, + ], + }, + ]; + assertDeepEqual(layouts, expected); + } + }); + }); });