Using mat4x4<f32> as uniform in WGSL

Viewed 91

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 Answers

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.)

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.

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,
        }
    );
Related