Search code examples
rustgpuwgpu-rswgsl

How to use Storage Buffers in WGPU to store dynamic sized arrays


I am working on a Pathtracer that uses the fragment-shader to render onto a Texture.

Currently I only render Spheres that are stored as a UniformBuffer like this:

var<uniform> geometry: Geometry;
struct Geometry {
    sphere_count: u32,
    spheres: array<Sphere, MAX_SPHERES>,
};
struct Sphere {
    position: vec3<f32>,
    color: vec3<f32>,
    radius: f32,
    roughness: f32,
};

But I want to render a variable amount of Voxel-Grids and because the size of one UniformBuffer seems to be limited to only 2^16 bytes I thought I would be a good Idea to store them in an array of 3D textures.

Is it possible to have all my textures in only one BindGroup like this:

var<uniform> texture_data: TextureData;
struct TextureData {
    texture_count: u32,
    texture_views: array<texture_3d<u32>, MAX_TEXTURES>;
    sampler: sampler;
};

Or is there any better way I could approach this problem?

Edit

I think using Storage Buffers is a better way but I have difficulties accessing dynamic sized arrays

I have the chunk-data stored like this on the shader:

var<storage, read> chunks: array<Chunk>;
struct Chunk {
    position: vec3<i32>,
    data: array<u32, CHUNK_SIZE>,
};

and in another uniform I have the total amount of chunks stored.

But when I try to access the chunks like this:

for (var index = 0u; index < globals.chunk_count; index = index + 1u) {
    let chunk = chunks[index];
}

The Program just hangs while creating the render pipeline.

If i replace chunks[index] with chunks[0] it seems to work.

I currently do not initialize the buffer with any data, so nothing is written to it upon its creation, but even when writing data to it to fill one Chunk in the array nothing is changed.

the Rust Chunk looks like this:

pub struct Chunk {
    position: [i32; 3],
    _padding: u32,
    data: [u32; TOTAL_CHUNK_SIZE],
}

Even when filling the whole buffer, which size I have set during device.create_buffer() with zeroes does seemingly nothing.

What is the proper way of using Storage buffers in WGPU to store dynamic sized arrays?


Solution

  • It all was just a problem of memory alignment.

    Changing the wgsl code to:

    @group(3)
    @binding(0)
    var<storage, read> chunks: array<Chunk>;
    struct Chunk {
        position: vec3<i32>,
        metadata: u32,
        data: array<vec4<u32>, CHUNK_SIZE>,
    };
    

    Seems to fix the problem.

    I am assuming that the array stride of data must be a multiple of 16 so i changed u32 to vec4<u32> and quartered CHUNK_SIZE.

    I also added metadata to align data to 16 bytes.