anvilkit_render/renderer/
assets.rs1use std::collections::HashMap;
7use std::sync::atomic::{AtomicU64, Ordering};
8
9use bevy_ecs::prelude::*;
10use wgpu::{Buffer, RenderPipeline, BindGroup, IndexFormat};
11
12use crate::renderer::RenderDevice;
13use crate::renderer::buffer::{Vertex, create_vertex_buffer, create_index_buffer, create_index_buffer_u32};
14
15static NEXT_HANDLE_ID: AtomicU64 = AtomicU64::new(1);
16
17fn next_id() -> u64 {
18 NEXT_HANDLE_ID.fetch_add(1, Ordering::Relaxed)
19}
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Component)]
23pub struct MeshHandle(pub u64);
24
25impl MeshHandle {
26 pub fn index(&self) -> u64 { self.0 }
28}
29
30#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Component)]
32pub struct MaterialHandle(pub u64);
33
34impl MaterialHandle {
35 pub fn index(&self) -> u64 { self.0 }
37}
38
39#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
43pub struct PipelineHandle(pub u64);
44
45pub struct GpuMesh {
47 pub vertex_buffer: Buffer,
48 pub index_buffer: Buffer,
49 pub index_count: u32,
50 pub index_format: IndexFormat,
51}
52
53pub struct GpuMaterial {
57 pub pipeline_handle: PipelineHandle,
58 pub bind_group: BindGroup,
59}
60
61#[derive(Resource, Default)]
65pub struct RenderAssets {
66 meshes: HashMap<MeshHandle, GpuMesh>,
67 materials: HashMap<MaterialHandle, GpuMaterial>,
68 pipelines: HashMap<PipelineHandle, RenderPipeline>,
69}
70
71impl RenderAssets {
72 pub fn upload_mesh<V: Vertex>(
74 &mut self,
75 device: &RenderDevice,
76 vertices: &[V],
77 indices: &[u16],
78 label: &str,
79 ) -> MeshHandle {
80 let vertex_buffer = create_vertex_buffer(device, &format!("{} VB", label), vertices);
81 let index_buffer = create_index_buffer(device, &format!("{} IB", label), indices);
82 let handle = MeshHandle(next_id());
83 self.meshes.insert(handle, GpuMesh {
84 vertex_buffer,
85 index_buffer,
86 index_count: indices.len() as u32,
87 index_format: IndexFormat::Uint16,
88 });
89 handle
90 }
91
92 pub fn upload_mesh_u32<V: Vertex>(
94 &mut self,
95 device: &RenderDevice,
96 vertices: &[V],
97 indices: &[u32],
98 label: &str,
99 ) -> MeshHandle {
100 let vertex_buffer = create_vertex_buffer(device, &format!("{} VB", label), vertices);
101 let index_buffer = create_index_buffer_u32(device, &format!("{} IB", label), indices);
102 let handle = MeshHandle(next_id());
103 self.meshes.insert(handle, GpuMesh {
104 vertex_buffer,
105 index_buffer,
106 index_count: indices.len() as u32,
107 index_format: IndexFormat::Uint32,
108 });
109 handle
110 }
111
112 pub fn register_pipeline(&mut self, pipeline: RenderPipeline) -> PipelineHandle {
116 let handle = PipelineHandle(next_id());
117 self.pipelines.insert(handle, pipeline);
118 handle
119 }
120
121 pub fn create_material_with_pipeline(
128 &mut self,
129 pipeline_handle: PipelineHandle,
130 bind_group: BindGroup,
131 ) -> MaterialHandle {
132 let handle = MaterialHandle(next_id());
133 self.materials.insert(handle, GpuMaterial {
134 pipeline_handle,
135 bind_group,
136 });
137 handle
138 }
139
140 pub fn create_material(
144 &mut self,
145 pipeline: RenderPipeline,
146 bind_group: BindGroup,
147 ) -> MaterialHandle {
148 let pipeline_handle = self.register_pipeline(pipeline);
149 self.create_material_with_pipeline(pipeline_handle, bind_group)
150 }
151
152 pub fn get_mesh(&self, handle: &MeshHandle) -> Option<&GpuMesh> {
154 self.meshes.get(handle)
155 }
156
157 pub fn get_material(&self, handle: &MaterialHandle) -> Option<&GpuMaterial> {
159 self.materials.get(handle)
160 }
161
162 pub fn get_pipeline(&self, handle: &PipelineHandle) -> Option<&RenderPipeline> {
164 self.pipelines.get(handle)
165 }
166
167 pub fn remove_mesh(&mut self, handle: &MeshHandle) -> bool {
169 self.meshes.remove(handle).is_some()
170 }
171
172 pub fn remove_material(&mut self, handle: &MaterialHandle) -> bool {
174 self.materials.remove(handle).is_some()
175 }
176
177 pub fn remove_pipeline(&mut self, handle: &PipelineHandle) -> bool {
182 self.pipelines.remove(handle).is_some()
183 }
184
185 pub fn mesh_count(&self) -> usize {
187 self.meshes.len()
188 }
189
190 pub fn material_count(&self) -> usize {
192 self.materials.len()
193 }
194
195 pub fn pipeline_count(&self) -> usize {
197 self.pipelines.len()
198 }
199}