macro_rules! shader_struct {
{ $struct:ident [
$( $num:tt $field:ident => $ty:ident ),* $(,)?
] } => { ... };
}Expand description
Define a shader struct (to use in a storage or uniform buffer).
Give each field a name and a standard shader type from shaderprimitive.
Uniform buffers are another can of worms, with their own weird alignment rules. The best way to deal with them is probably to make
Note that fields must be numbered correctly, starting from 0. This is
because I don’t know how to teach macros how to count and still be able to
index tuples.
Also, the fields are not rearranged to be optimized to their alignment
rules, though they should be padded correctly for regular shader structs.
shader_struct! { ShaderStruct [
0 int => I32,
1 mat => Mat4x4f,
2 float => F32,
] }
buffer! { ShaderBuffer <ShaderStruct> as STORAGE | COPY_DST }
// Big enough to store 10 ShaderStructs, including padding
let buffer: ShaderBuffer = context.new_buffer(10);When you create a shader struct on the Rust side, its memory layout should match exactly as it is shader-side. You can write directly to each field (though everything’s in arrays) and then safely-ish transmute it to a byte slice to write to the buffer.
let single_struct: ShaderStruct = (
[5_i32],
[[0.0, 1.0, 2.0, 3.0]; 4],
[4.0],
).into();
let mut lotsa_structs = [single_struct; 10];
*lotsa_structs[7].float = [5.0];
context.queue.write_buffer(
&buffer,
some_offset * size_of::<ShaderStruct>() as u64,
lotsa_structs.as_byte_slice(),
);