brendan-duncan/wgsl_reflect

No reflection data for raw arrays

greggman opened this issue · 5 comments

If I have a shader that has

@binding(0) @group(0) var<uniform> viewUniforms: array<vec4<f32>, 7>;

It appears the no reflection data is returned. Sorry, I didn't try to fix it myself yet.

I'm going to guess that raw non-arrays have the same issue

@binding(0) @group(0) var<uniform> viewUniforms: f32;

Oversight on my part. I assumed without looking that uniform buffers could only be structs, but it makes sense they can be anything. I'll get that fixed tonight after I get through my day job work :-)

See if this works for you.

struct ViewUniforms {
  viewProjection: mat4x4<f32>
};
        
struct ModelUniforms {
  model: mat4x4<f32>,
  color: vec4<f32>,
  intensity: f32,
  view: array<ViewUniforms,2>,
  f32Array: array<f32,2>
};
@group(0) @binding(0) var<uniform> model : ModelUniforms;
@binding(1) @group(0) var<uniform> uArray: array<vec4<f32>, 7>;
@binding(2) @group(0) var<uniform> uFloat: f32;
      const u0 = reflect.getUniformBufferInfo(reflect.uniforms[0]);
      test.equals(u0.name, 'model');
      test.equals(u0.type.name, 'ModelUniforms');
      test.equals(u0.members.length, 5);
      test.equals(u0.size, 240);
      
      const u1 = reflect.getUniformBufferInfo(reflect.uniforms[1]);
      test.equals(u1.name, 'uArray');
      test.equals(u1.type.name, 'array');
      test.equals(u1.type.format.name, 'vec4');
      test.equals(u1.type.format.format.name, 'f32');
      test.equals(u1.size, 112);
      test.equals(u1.align, 16);

      const u2 = reflect.getUniformBufferInfo(reflect.uniforms[2]);
      test.equals(u2.name, 'uFloat');
      test.equals(u2.type.name, 'f32');
      test.equals(u2.size, 4);
      test.equals(u2.align, 4);

Thanks Brendan!

I'm wondering though... If I have this

struct Test {
    foo: array<vec3<f32>, 16>,
};
@group(0) @binding(0) var<uniform> myUniformsStruct: Test;
@group(0) @binding(1) var<uniform> myUniformsArray: array<vec3<f32>, 16>;

Somewhere I'd expect the data I get for myUniformArray to be similar to the data I get for myUniformStruct.foo as they're the same.

Currently, for myUniformStruct.foo I get

arrayCount: 16
arrayStride: 12
isArray: true
isStruct: false
member: AST {_type: 'member', name: 'foo', attributes: null, type: AST}
members: undefined
name: "foo"
offset: 0
size: 256
type: AST {_type: 'array', name: 'array', attributes: null, format: AST, count: '16'}

but for myUniformArray I get

align: 16
binding: 1
group: 0
name: "myUniformsArray"
size: 256
type: AST {_type: 'array', name: 'array', attributes: null, format: AST, count: '16'}

would it make sense for the info for myUniformArray to include isArray, isStruct, arrayCount, arrayStride? Then, to the outside code, the 2 are the same.

Maybe getUniformBufferInfo could return

binding: 1
group: 0
size: 256
memberDefinition: ???

Where memberDefinition is the data returned for a member of a struct (since a member of a struct can be a base type, an array of base types, a struct, an array of structs. And similarly, getStructInfo would also return a "memberDefinition" that happens to be struct, since again, the data for a nested struct should be the same as the data for a top level struct.

Yeah you're right, they should be the same. I added isArray, isStruct, arrayCount, arrayStride to the non-struct case.

I'm not sure I follow the memberDefinition suggestion, maybe you can mock that up. I'm all for finding a clean and consistent API.