For data containing arrays whose length is determined at runtime, use the ArrayLength type and the #[shader(size(runtime))] attribute within your ShaderType struct. This works with StorageBuffer to handle the layout of variable-length data.
use encase::{ShaderType, ArrayLength, StorageBuffer};
#[derive(ShaderType)]
struct Positions {
length: ArrayLength,
#[shader(size(runtime))]
positions: Vec<test_impl::Vec2f>
}
let mut positions = Positions {
length: ArrayLength,
positions: Vec::from([
test_impl::Vec2f::from([4.5, 3.4]),
test_impl::Vec2f::from([1.5, 7.4]),
test_impl::Vec2f::from([4.3, 1.9]),
]),
};
let mut byte_buffer: Vec<u8> = Vec::new();
let mut buffer = StorageBuffer::new(&mut byte_buffer);
buffer.write(&positions).unwrap();
// To read back after GPU modification:
// byte_buffer[0] = 2; // e.g. changing length on GPU
// buffer.read(&mut positions).unwrap();
use encase::{ShaderType, ArrayLength, StorageBuffer};
#[derive(ShaderType)]
struct Positions {
length: ArrayLength,
#[shader(size(runtime))]
positions: Vec<test_impl::Vec2f>
}
let mut positions = Positions {
length: ArrayLength,
positions: Vec::from([
test_impl::Vec2f::from([4.5, 3.4]),
test_impl::Vec2f::from([1.5, 7.4]),
test_impl::Vec2f::from([4.3, 1.9]),
])
};
let mut byte_buffer: Vec<u8> = Vec::new();
let mut buffer = StorageBuffer::new(&mut byte_buffer);
buffer.write(&positions).unwrap();
// write byte_buffer to GPU
// change length on GPU side
byte_buffer[0] = 2;
// read byte_buffer from GPU
let mut buffer = StorageBuffer::new(&mut byte_buffer);
buffer.read(&mut positions).unwrap();
assert_eq!(positions.positions.len(), 2);