use super::super::world_state::WorldGpuBuffers;
use super::MeshPass;
impl MeshPass {
pub(in super::super) fn rebuild_instance_bind_group(&mut self, device: &wgpu::Device) {
let world_state = self.world_states.get_mut(&self.current_world_id).unwrap();
let gpu = world_state.gpu_buffers.as_mut().unwrap();
gpu.instance_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Mesh Instance Bind Group"),
layout: &self.instance_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu.transform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: gpu.materials_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: gpu.object_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 3,
resource: gpu.lights_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 4,
resource: gpu.visible_indices_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 5,
resource: gpu.custom_data_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 6,
resource: self.morph_displacement_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 7,
resource: gpu.light_grid_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 8,
resource: gpu.light_indices_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 9,
resource: gpu.cluster_uniforms_buffer.as_entire_binding(),
},
],
});
gpu.phase1_instance_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Phase 1 Instance Bind Group"),
layout: &self.instance_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu.transform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: gpu.materials_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: gpu.object_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 3,
resource: gpu.lights_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 4,
resource: gpu.phase1_visible_indices_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 5,
resource: gpu.custom_data_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 6,
resource: self.morph_displacement_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 7,
resource: gpu.light_grid_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 8,
resource: gpu.light_indices_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 9,
resource: gpu.cluster_uniforms_buffer.as_entire_binding(),
},
],
});
gpu.cluster_bounds_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Cluster Bounds Bind Group (Per-World)"),
layout: &self._cluster_bounds_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu.cluster_uniforms_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: self.cluster_bounds_buffer.as_entire_binding(),
},
],
});
}
pub(in super::super) fn invalidate_all_instance_bind_groups(&mut self, device: &wgpu::Device) {
let world_ids: Vec<u64> = self.world_states.keys().copied().collect();
let saved_world_id = self.current_world_id;
for world_id in world_ids {
if self
.world_states
.get(&world_id)
.unwrap()
.gpu_buffers
.is_some()
{
self.current_world_id = world_id;
self.rebuild_instance_bind_group(device);
}
}
self.current_world_id = saved_world_id;
}
pub(in super::super) fn rebuild_transform_compute_bind_group(&mut self, device: &wgpu::Device) {
let world_state = self.world_states.get_mut(&self.current_world_id).unwrap();
let gpu = world_state.gpu_buffers.as_mut().unwrap();
gpu.transform_compute_bind_group =
Some(device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Transform Compute Bind Group"),
layout: &self.transform_compute_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu.local_transform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: gpu.transform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: self.transform_compute_uniforms_buffer.as_entire_binding(),
},
],
}));
}
pub(in super::super) fn rebuild_instanced_compute_bind_group(&mut self, device: &wgpu::Device) {
let world_state = self.world_states.get_mut(&self.current_world_id).unwrap();
let gpu = world_state.gpu_buffers.as_mut().unwrap();
gpu.instanced_compute_bind_group =
Some(device.create_bind_group(&wgpu::BindGroupDescriptor {
label: Some("Instanced Transform Compute Bind Group"),
layout: &self.instanced_compute_bind_group_layout,
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: gpu.instanced_local_matrix_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 1,
resource: gpu.transform_buffer.as_entire_binding(),
},
wgpu::BindGroupEntry {
binding: 2,
resource: self.instanced_compute_uniforms_buffer.as_entire_binding(),
},
],
}));
}
pub(in super::super) fn ensure_world_gpu_buffers(
&mut self,
device: &wgpu::Device,
world_id: u64,
) {
self.world_states.entry(world_id).or_default();
let state = self.world_states.get_mut(&world_id).unwrap();
if state.gpu_buffers.is_none() {
state.gpu_buffers = Some(WorldGpuBuffers::new(
device,
&self.instance_bind_group_layout,
&self._cluster_bounds_bind_group_layout,
&self.cluster_bounds_buffer,
&self.morph_displacement_buffer,
));
}
}
pub fn cleanup_world_state(&mut self, world_id: u64) {
if self.last_prepared_world_id == Some(world_id) {
self.last_prepared_world_id = None;
}
self.world_states.remove(&world_id);
}
pub fn cleanup_stale_world_states(&mut self, max_age_frames: u64) {
let current_frame = self.frame_counter;
let stale_world_ids: Vec<u64> = self
.world_states
.iter()
.filter(|(world_id, state)| {
**world_id != self.last_prepared_world_id.unwrap_or(u64::MAX)
&& current_frame.saturating_sub(state.last_used_frame) > max_age_frames
})
.map(|(world_id, _)| *world_id)
.collect();
for world_id in stale_world_ids {
self.world_states.remove(&world_id);
}
}
}