wde_pbr/deferred/batches/
ssbo_batches.rs1use bevy::{ecs::system::SystemParamItem, prelude::*};
2use wde_renderer::prelude::*;
3
4use crate::prelude::BatchList;
5
6pub const SSBO_MAX_BATCHES: usize = 100_000;
8
9pub(crate) struct SsboInstancesToTransformPlugin;
10impl Plugin for SsboInstancesToTransformPlugin {
11 fn build(&self, app: &mut App) {
12 app.add_plugins(RenderDataRegisterPlugin::<PbrSsboInstanceToTransform>::default());
13 }
14}
15
16#[derive(Asset, Clone, TypePath, Default)]
18pub struct PbrSsboInstanceToTransform;
19impl PbrSsboInstanceToTransform {
20 pub const INSTANCE_TO_TRANSFORM_IDX: u32 = 0;
21 pub const INSTANCE_TO_TRANSFORM_STAGING_IDX: u32 = 1;
22}
23impl RenderData for PbrSsboInstanceToTransform {
24 type Params = ();
25
26 fn describe(_params: &mut SystemParamItem<Self::Params>, builder: &mut RenderDataBuilder) {
27 builder
28 .add_buffer(
29 Self::INSTANCE_TO_TRANSFORM_IDX,
30 Buffer {
31 label: "pbr-instance-to-transform-buffer-gpu".to_string(),
32 size: std::mem::size_of::<u32>() * SSBO_MAX_BATCHES,
33 usage: BufferUsage::STORAGE | BufferUsage::COPY_DST,
34 content: None,
35 },
36 )
37 .add_buffer(
38 Self::INSTANCE_TO_TRANSFORM_STAGING_IDX,
39 Buffer {
40 label: "pbr-instance-to-transform-staging".to_string(),
41 size: std::mem::size_of::<u32>() * SSBO_MAX_BATCHES,
42 usage: BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
43 content: None,
44 },
45 );
46 }
47}
48
49pub(crate) fn set_instances_to_transform(
50 instance_to_transform: ResRenderData<PbrSsboInstanceToTransform>,
51 mut batches: ResMut<BatchList>,
52 buffers: Res<RenderAssets<GpuBuffer>>,
53 render_instance: Res<RenderInstance>,
54) {
55 if batches.dirty_batches.is_empty() {
57 return;
58 }
59
60 let instance_to_transform = match instance_to_transform.iter().next() {
62 Some((_, data)) => data,
63 None => return
64 };
65 let (staging_buffer, gpu_buffer) = match (
66 buffers.get(&instance_to_transform.get_buffer(PbrSsboInstanceToTransform::INSTANCE_TO_TRANSFORM_STAGING_IDX).unwrap()),
67 buffers.get(&instance_to_transform.get_buffer(PbrSsboInstanceToTransform::INSTANCE_TO_TRANSFORM_IDX).unwrap()),
68 ) {
69 (Some(staging), Some(gpu)) => (staging, gpu),
70 _ => return
71 };
72
73 let mut staging_content = vec![0u8; staging_buffer.buffer.buffer.size() as usize];
75 let mut offset = 0;
76 for batch_key in batches.dirty_batches.clone().iter() {
77 let batch = batches.batches.get_mut(batch_key).unwrap();
78 batch.instances_offset = offset;
79 for transform_id in &batch.transform_ssbo_ids {
80 let bytes = transform_id.to_ne_bytes();
81 staging_content[(offset as usize * 4)..((offset as usize + 1) * 4)].copy_from_slice(&bytes);
82 offset += 1;
83 }
84 }
85 let render_instance = render_instance.0.read().unwrap();
86 staging_buffer.buffer.write(&render_instance, &staging_content, 0);
87
88 gpu_buffer.buffer.copy_from_buffer(&render_instance, &staging_buffer.buffer);
90
91 batches.dirty_batches.clear();
93}