Is it possible to do partial shader storage buffer rewrites? #22791
-
|
Hi. I've used a material2d to instance entities into a single draw call, and I store the data I send over to the gpu in a Hashmap. I made my own frustum culling to avoid some issues with instancing and so that I only need to update some entries in the Hashmap. But the thing is that, for what I understand, when you try to update the shader storage buffer of the material, it seems to expose only set_data() which fully rewrites the buffer, this kinda defeats the point of everything I did since I still have to build a vector from the hashmap and give it that, while I could directly update the stale data. So I wanted to know if there's any other way to do it while still using materials? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
|
@FeatheredOrbit bevy's the fix: drop to the render world and use wgpu's
let ssbo = ShaderStorageBuffer::with_size(
max_instances * std::mem::size_of::<InstanceData>(),
RenderAssetUsages::RENDER_WORLD,
);
#[derive(Resource)]
struct DirtyInstances(Vec<(usize, InstanceData)>);
fn partial_update_ssbo(
render_queue: Res<RenderQueue>,
gpu_ssbos: Res<RenderAssets<GpuShaderStorageBuffer>>,
dirty: Res<DirtyInstances>,
handle: Res<SsboHandle>,
) {
let Some(gpu_ssbo) = gpu_ssbos.get(&handle.0) else { return };
for &(index, ref data) in &dirty.0 {
let offset = (index * std::mem::size_of::<InstanceData>()) as u64;
let bytes = bytemuck::bytes_of(data);
render_queue.write_buffer(&gpu_ssbo.buffer, offset, bytes);
}
}important: don't call re: ref: ShaderStorageBuffer docs | RenderQueue | wgpu Queue::write_buffer | bevy render stages |
Beta Was this translation helpful? Give feedback.
@FeatheredOrbit bevy's
ShaderStorageBuffer::set_data()has no partial update support. looking at the source, it serializes the entire value via encase into a newVec<u8>, thenprepare_assetcreates a brand new GPU buffer every call. none of bevy's built-in buffer types (StorageBuffer,DynamicStorageBuffer,RawBufferVec) support partial GPU writes with offsets either.the fix: drop to the render world and use
RenderQueue::write_buffer()directlywgpu's
Queue::write_buffer()supports offset-based partial writes natively, and bevy'sRenderQueuederefs to it.GpuShaderStorageBufferexposes the underlyingbufferfield as pub.let…