Using mat4x4<f32> as uniform in WGSL

958 views Asked by At

Is it possible to use a mat4x4<f32> as a uniform data type in WGSL?

I get the following error when doing so:

Shader validation error: 
   ┌─ Shader:18:4
   │
18 │ var<uniform> model: mat4x4<f32>;
   │    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ naga::GlobalVariable [1]


    Global variable [1] 'model' is invalid
    Type isn't compatible with the storage class

Wrapping in a struct is fine and achieves what I need, but seems superfluous. Can the matrix type be used directly?

3

There are 3 answers

0
David Neto On

WGSL used to require a struct as the type of a uniform or storage buffer. But WGSL is now more flexible, and (that version of) Naga is not yet caught up.

0
dj2 On

I think that's a Naga bug. The following appears to compile correctly in Tint.

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

@compute @workgroup_size(1)
fn main() {
  var f = model[0][0];
}

The uniform should accept any constructable, host-shareable type (things like vectors, matrices, structs, etc.)

0
user3054986 On

Would be nice to have seen your code. "It works on my machine": (naga 0.9.0, wgpu 0.13.1, winit 0.26.1)

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

    @fragment
    fn fs_main(@builtin(position) coord_in: vec4<f32>) -> @location(0) vec4<f32> {
        return vec4<f32>(color.y);
    }

on the rust side:

    let color_uniform: [[f32; 4]; 4] = [
        [1.0, 0.0, 0.0, 1.0],
        [0.0, 0.5, 0.0, 1.0],
        [0.0, 0.0, 1.0, 1.0],
        [1.0, 1.0, 0.0, 1.0],
    ];

    let uniform_buffer = device.create_buffer_init(
        &wgpu::util::BufferInitDescriptor {
            label: Some("Uniform Buffer"),
            contents: bytemuck::cast_slice(&[color_uniform]),
            usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
        }
    );