Using wgpu-rs, I'm trying to get a 3x3 cgmath matrix into a shader (compiled using glsl-to-spirv). However, the resulting mat3 in the shader has incorrect data. When I replace the mat3 and Matrix3 with mat4 and Matrix4, everything works fine and the matrix has correct data.
Vertex Shader:
layout(set=0, binding=0) uniform Uniforms {
mat3 camera_transform;
};
Render Loop:
let mut encoder = self.device.create_command_encoder(
&wgpu::CommandEncoderDescriptor {
label: Some("update encoder"),
},
);
let staging_buffer = self.device.create_buffer_with_data(
bytemuck::cast_slice(&[self.uniforms]),
wgpu::BufferUsage::COPY_SRC,
);
encoder.copy_buffer_to_buffer(&staging_buffer, 0, &self.uniform_buffer, 0, std::mem::size_of::<Uniforms>() as wgpu::BufferAddress);
self.queue.submit(&[encoder.finish()]);
// ...
render_pass.set_bind_group(0, &self.uniform_bind_group, &[]);
Uniforms:
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Uniforms {
pub camera_transform: Matrix3::<f32>,
}
unsafe impl bytemuck::Pod for Uniforms {}
unsafe impl bytemuck::Zeroable for Uniforms {}
impl Uniforms {
pub fn new() -> Self {
Self {
camera_transform: Matrix3::identity(),
}
}
}
This is an open issue in wgpu-rs
. Indeed the simplest workaround may be to make your mat3 into a mat4 until it is resolved.
The problem seems to be a mistake of alignment in generating SPIR-V
. The actual alignment is:
- If the member is a scalar consuming N basic machine units, the base alignment is N.
- If the member is a two- or four-component vector with components consuming N basic machine units, the base alignment is 2N or 4N, respectively.
- If the member is a three-component vector with components consuming N basic machine units, the base alignment is 4N.
- If the member is an array of scalars or vectors, the base alignment and array stride are set to match the base alignment of a single array element, according to rules (1), (2), and (3), and rounded up to the base alignment of a vec4. The array may have padding at the end; the base offset of the member following the array is rounded up to the next multiple of the base alignment.
You are in case 4. Having a mat4 should leave no extra padding on the end and not give any possibility for misalignment issues.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With