rust 如何在WGPU中使用存储缓冲区来存储动态大小的数组

qyyhg6bp  于 2023-03-02  发布在  其他
关注(0)|答案(1)|浏览(109)

我正在研究一个使用碎片着色器渲染到纹理上的路径跟踪器。
目前我只渲染存储为UniformBuffer的球体,如下所示:

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,
};

但是我想渲染一个可变数量的体素网格,因为一个均匀缓冲区的大小似乎被限制在只有2^16字节,我想我会是一个好主意,存储在一个3D纹理数组。
是否可以像这样将所有纹理都放在一个BindGroup中:

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

或者有没有更好的方法来解决这个问题?

编辑

我认为使用存储缓冲区是一种更好的方法,但我在访问动态大小的阵列时遇到了困难
我在着色器上存储了块数据,如下所示:

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

而在另一个统一中,我有存储的块的总量。
但是当我试着像这样访问这些块时:

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

程序只是在创建渲染管道时挂起。
如果我用chunks[0]替换chunks[index],它似乎可以工作。
我目前没有使用任何数据初始化缓冲区,因此在创建缓冲区时没有向其中写入任何内容,但即使向其中写入数据以填充数组中的一个Chunk,也没有任何更改。
Rust Chunk看起来像这样:

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

即使在填充整个缓冲区时,我在device.create_buffer()期间用零设置的大小似乎也没有什么作用。
在WGPU中使用存储缓冲区来存储动态大小的数组的正确方法是什么?

vs91vp4v

vs91vp4v1#

这一切只是记忆对齐的问题。
将wgsl代码更改为:

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

似乎解决了问题。
我假设data的数组跨距必须是16的倍数,因此我将u32更改为vec4<u32>,并将CHUNK_SIZE四等分。
我还添加了metadata,以便将data对齐到16个字节。

相关问题