vulkano icon indicating copy to clipboard operation
vulkano copied to clipboard

How to construct unsized types for shader

Open KarelPeeters opened this issue 4 years ago • 3 comments

This isn't really an issue per se, more of a question. I couldn't find anything about this in the documentation, but I might be missing something.

I'm trying to pass some data to a compute shader with an input like this:

struct Sphere {
    vec2 pos;
    float r;
};

layout(set = 0, binding = 1) readonly buffer Objects {
    Sphere spheres[];
};

The vulkano_shaders::shader! macro generates Rust equivalents to theses structs, they look like this:

#[repr(C)]
#[allow(non_snake_case)]
pub struct Sphere {
    pub pos: [f32; 2usize],
    pub r: f32,
    pub _dummy0: [u8; 4u32 as usize],
}

#[repr(C)]
#[allow(non_snake_case)]
pub struct Objects {
    pub spheres: [Sphere],
}

How do I construct an Objects instance in Rust? My understanding is that you can't really create unsized structs, https://github.com/rust-lang/rust/issues/18598 isn't stable yet.

In this case I can create a Vec<Sphere> and put that in a buffer using CpuAccessibleBuffer::from_iter, but that's brittle if anything about Objects ever changes. Is there another more typesafe way to do this?

KarelPeeters avatar Mar 06 '20 13:03 KarelPeeters

Another related question:

Is there an easy way to create instances of structs like Sphere without having to specify the dummy fields all the time? Or should I just write my own Sphere struct and then write some convertor functions?

KarelPeeters avatar Mar 06 '20 14:03 KarelPeeters

@flaghacker

Is there an easy way to create instances of structs like Sphere without having to specify the dummy fields all the time?

You can define impl Default for each type you are actively using in your code that will fill all the fields with defaults including dummies, then instantiate them through Sphere::default().

Eliah-Lakhin avatar Mar 09 '20 10:03 Eliah-Lakhin

@Eliah-Lakhin I could do that but then I might forget to initialize any fields I might add in the future, but it looks like that's indeed the best solution for now. Thanks!

KarelPeeters avatar Mar 12 '20 15:03 KarelPeeters

I'm thinking that for cases like this, the generated struct should have a const usize parameter specifying the size of the array. So it should be this:

#[repr(C)]
#[allow(non_snake_case)]
pub struct Objects<const NSPHERES: usize> {
    pub spheres: [Sphere; NSPHERES],
}

Rua avatar Dec 28 '22 18:12 Rua

That's not always general enough, in my case the length was not known at compile time.

KarelPeeters avatar Dec 30 '22 23:12 KarelPeeters