Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_pbr/src/meshlet/meshlet_mesh_manager.rs
6600 views
1
use crate::meshlet::asset::{BvhNode, MeshletAabb, MeshletCullData};
2
3
use super::{asset::Meshlet, persistent_buffer::PersistentGpuBuffer, MeshletMesh};
4
use alloc::sync::Arc;
5
use bevy_asset::{AssetId, Assets};
6
use bevy_ecs::{
7
resource::Resource,
8
system::{Commands, Res, ResMut},
9
};
10
use bevy_math::Vec2;
11
use bevy_platform::collections::HashMap;
12
use bevy_render::{
13
render_resource::BufferAddress,
14
renderer::{RenderDevice, RenderQueue},
15
};
16
use core::ops::Range;
17
18
/// Manages uploading [`MeshletMesh`] asset data to the GPU.
19
#[derive(Resource)]
20
pub struct MeshletMeshManager {
21
pub vertex_positions: PersistentGpuBuffer<Arc<[u32]>>,
22
pub vertex_normals: PersistentGpuBuffer<Arc<[u32]>>,
23
pub vertex_uvs: PersistentGpuBuffer<Arc<[Vec2]>>,
24
pub indices: PersistentGpuBuffer<Arc<[u8]>>,
25
pub bvh_nodes: PersistentGpuBuffer<Arc<[BvhNode]>>,
26
pub meshlets: PersistentGpuBuffer<Arc<[Meshlet]>>,
27
pub meshlet_cull_data: PersistentGpuBuffer<Arc<[MeshletCullData]>>,
28
meshlet_mesh_slices:
29
HashMap<AssetId<MeshletMesh>, ([Range<BufferAddress>; 7], MeshletAabb, u32)>,
30
}
31
32
pub fn init_meshlet_mesh_manager(mut commands: Commands, render_device: Res<RenderDevice>) {
33
commands.insert_resource(MeshletMeshManager {
34
vertex_positions: PersistentGpuBuffer::new("meshlet_vertex_positions", &render_device),
35
vertex_normals: PersistentGpuBuffer::new("meshlet_vertex_normals", &render_device),
36
vertex_uvs: PersistentGpuBuffer::new("meshlet_vertex_uvs", &render_device),
37
indices: PersistentGpuBuffer::new("meshlet_indices", &render_device),
38
bvh_nodes: PersistentGpuBuffer::new("meshlet_bvh_nodes", &render_device),
39
meshlets: PersistentGpuBuffer::new("meshlets", &render_device),
40
meshlet_cull_data: PersistentGpuBuffer::new("meshlet_cull_data", &render_device),
41
meshlet_mesh_slices: HashMap::default(),
42
});
43
}
44
45
impl MeshletMeshManager {
46
// Returns the index of the root BVH node, as well as the depth of the BVH.
47
pub fn queue_upload_if_needed(
48
&mut self,
49
asset_id: AssetId<MeshletMesh>,
50
assets: &mut Assets<MeshletMesh>,
51
) -> (u32, MeshletAabb, u32) {
52
let queue_meshlet_mesh = |asset_id: &AssetId<MeshletMesh>| {
53
let meshlet_mesh = assets.remove_untracked(*asset_id).expect(
54
"MeshletMesh asset was already unloaded but is not registered with MeshletMeshManager",
55
);
56
57
let vertex_positions_slice = self
58
.vertex_positions
59
.queue_write(Arc::clone(&meshlet_mesh.vertex_positions), ());
60
let vertex_normals_slice = self
61
.vertex_normals
62
.queue_write(Arc::clone(&meshlet_mesh.vertex_normals), ());
63
let vertex_uvs_slice = self
64
.vertex_uvs
65
.queue_write(Arc::clone(&meshlet_mesh.vertex_uvs), ());
66
let indices_slice = self
67
.indices
68
.queue_write(Arc::clone(&meshlet_mesh.indices), ());
69
let meshlets_slice = self.meshlets.queue_write(
70
Arc::clone(&meshlet_mesh.meshlets),
71
(
72
vertex_positions_slice.start,
73
vertex_normals_slice.start,
74
indices_slice.start,
75
),
76
);
77
let base_meshlet_index = (meshlets_slice.start / size_of::<Meshlet>() as u64) as u32;
78
let bvh_node_slice = self
79
.bvh_nodes
80
.queue_write(Arc::clone(&meshlet_mesh.bvh), base_meshlet_index);
81
let meshlet_cull_data_slice = self
82
.meshlet_cull_data
83
.queue_write(Arc::clone(&meshlet_mesh.meshlet_cull_data), ());
84
85
(
86
[
87
vertex_positions_slice,
88
vertex_normals_slice,
89
vertex_uvs_slice,
90
indices_slice,
91
bvh_node_slice,
92
meshlets_slice,
93
meshlet_cull_data_slice,
94
],
95
meshlet_mesh.aabb,
96
meshlet_mesh.bvh_depth,
97
)
98
};
99
100
// If the MeshletMesh asset has not been uploaded to the GPU yet, queue it for uploading
101
let ([_, _, _, _, bvh_node_slice, _, _], aabb, bvh_depth) = self
102
.meshlet_mesh_slices
103
.entry(asset_id)
104
.or_insert_with_key(queue_meshlet_mesh)
105
.clone();
106
107
(
108
(bvh_node_slice.start / size_of::<BvhNode>() as u64) as u32,
109
aabb,
110
bvh_depth,
111
)
112
}
113
114
pub fn remove(&mut self, asset_id: &AssetId<MeshletMesh>) {
115
if let Some((
116
[vertex_positions_slice, vertex_normals_slice, vertex_uvs_slice, indices_slice, bvh_node_slice, meshlets_slice, meshlet_cull_data_slice],
117
_,
118
_,
119
)) = self.meshlet_mesh_slices.remove(asset_id)
120
{
121
self.vertex_positions
122
.mark_slice_unused(vertex_positions_slice);
123
self.vertex_normals.mark_slice_unused(vertex_normals_slice);
124
self.vertex_uvs.mark_slice_unused(vertex_uvs_slice);
125
self.indices.mark_slice_unused(indices_slice);
126
self.bvh_nodes.mark_slice_unused(bvh_node_slice);
127
self.meshlets.mark_slice_unused(meshlets_slice);
128
self.meshlet_cull_data
129
.mark_slice_unused(meshlet_cull_data_slice);
130
}
131
}
132
}
133
134
/// Upload all newly queued [`MeshletMesh`] asset data to the GPU.
135
pub fn perform_pending_meshlet_mesh_writes(
136
mut meshlet_mesh_manager: ResMut<MeshletMeshManager>,
137
render_queue: Res<RenderQueue>,
138
render_device: Res<RenderDevice>,
139
) {
140
meshlet_mesh_manager
141
.vertex_positions
142
.perform_writes(&render_queue, &render_device);
143
meshlet_mesh_manager
144
.vertex_normals
145
.perform_writes(&render_queue, &render_device);
146
meshlet_mesh_manager
147
.vertex_uvs
148
.perform_writes(&render_queue, &render_device);
149
meshlet_mesh_manager
150
.indices
151
.perform_writes(&render_queue, &render_device);
152
meshlet_mesh_manager
153
.bvh_nodes
154
.perform_writes(&render_queue, &render_device);
155
meshlet_mesh_manager
156
.meshlets
157
.perform_writes(&render_queue, &render_device);
158
meshlet_mesh_manager
159
.meshlet_cull_data
160
.perform_writes(&render_queue, &render_device);
161
}
162
163