[wgsl-in] Why can't I use mat2x2<f32> as an instance input?
AndriBaal opened this issue · comments
I have a shader with a mat2x2 as a part of my instance:
struct Camera {
view_proj: mat4x4<f32>
}
@group(0) @binding(0)
var<uniform> camera: Camera;
struct VertexInput {
@location(0) v_position: vec2<f32>,
@location(1) tex: vec2<f32>,
}
struct InstanceInput {
@location(2) i_position: vec2<f32>,
@location(3) rotation: mat2x2<f32>,
}
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex: vec2<f32>,
}
@vertex
fn main(
model: VertexInput,
instance: InstanceInput,
) -> VertexOutput {
var out: VertexOutput;
let pos = model.v_position * instance.rotation + instance.i_position;
out.clip_position = camera.view_proj * vec4<f32>(pos, 0.0, 1.0);
out.tex = model.tex;
return out;
}
However, this is not possible because I receive the following error:
thread 'main' panicked at 'wgpu error: Validation Error
Caused by:
In Device::create_shader_module
note: label = `sprite_sheet`
Shader validation error:
┌─ sprite_sheet:15:1
│
15 │ ╭ struct InstanceInput {
16 │ │ @location(2) i_position: vec2<f32>,
17 │ │ @location(3) rotation: mat2x2f,
18 │ │
19 │ │ @location(4) sprite: u32,
│ ╰────────────────────────────^ naga::Type [7]
Entry point main at Vertex is invalid
Argument 1 varying error
The type [5] cannot be used for user-defined entry point inputs or outputs
', /home/andri/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wgpu-0.17.1/src/backend/direct.rs:3056:5
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
I have developed the followng workaround:
struct Camera {
view_proj: mat4x4<f32>
}
@group(0) @binding(0)
var<uniform> camera: Camera;
struct VertexInput {
@location(0) v_position: vec2<f32>,
@location(1) tex: vec2<f32>,
}
struct InstanceInput {
@location(2) i_position: vec2<f32>,
@location(3) rotation: vec4<f32>,
}
struct VertexOutput {
@builtin(position) clip_position: vec4<f32>,
@location(0) tex: vec2<f32>,
}
@vertex
fn main(
model: VertexInput,
instance: InstanceInput,
) -> VertexOutput {
var out: VertexOutput;
let pos = model.v_position * mat2x2<f32>(instance.rotation.xy, instance.rotation.zw) + instance.i_position;
out.clip_position = camera.view_proj * vec4<f32>(pos, 0.0, 1.0);
out.tex = model.tex;
return out;
}
This workaround replaces the mat2x2 with a vec4 since vectors are allowed. The reason I need a mat2x2 is because I need to multiply with a vec2 which is not possible with a vec4. Later in the shader I build my matrix from the vector. My concerns are that this might be slower than just accepting the mat2x2 directly from the instance input. Is there any reason why mat2x2 is not allowed here? Or might the compiler optimize it anyway, so it does not make a difference?
It's a restriction imposed by the WGSL spec. Most likely due to the shading languages we target also not supporting matrices for vertex/instance inputs.
Or might the compiler optimize it anyway, so it does not make a difference?
It's most likely that it doesn't make a difference. Most compilers will scalarize matrices and vectors anyway.