我正在研究一个使用碎片着色器渲染到纹理上的路径跟踪器。
目前我只渲染存储为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中使用存储缓冲区来存储动态大小的数组的正确方法是什么?
1条答案
按热度按时间vs91vp4v1#
这一切只是记忆对齐的问题。
将wgsl代码更改为:
似乎解决了问题。
我假设
data
的数组跨距必须是16的倍数,因此我将u32
更改为vec4<u32>
,并将CHUNK_SIZE
四等分。我还添加了
metadata
,以便将data
对齐到16个字节。