dear_imgui_wgpu/
frame_resources.rs1use dear_imgui_rs::render::{DrawIdx, DrawVert};
7use wgpu::*;
8
9fn align_size(size: usize, alignment: usize) -> usize {
12 (size + alignment - 1) & !(alignment - 1)
13}
14
15pub struct FrameResources {
20 pub vertex_buffer: Option<Buffer>,
22 pub index_buffer: Option<Buffer>,
24 pub vertex_buffer_host: Option<Vec<u8>>,
26 pub index_buffer_host: Option<Vec<u8>>,
28 pub vertex_buffer_size: usize,
30 pub index_buffer_size: usize,
32}
33
34impl FrameResources {
35 pub fn new() -> Self {
37 Self {
38 vertex_buffer: None,
39 index_buffer: None,
40 vertex_buffer_host: None,
41 index_buffer_host: None,
42 vertex_buffer_size: 0,
43 index_buffer_size: 0,
44 }
45 }
46
47 pub fn ensure_vertex_buffer_capacity(
49 &mut self,
50 device: &Device,
51 required_vertices: usize,
52 ) -> Result<(), String> {
53 if self.vertex_buffer.is_none() || self.vertex_buffer_size < required_vertices {
54 let new_size = (required_vertices + 5000).max(self.vertex_buffer_size * 2);
56
57 let buffer_size = align_size(new_size * std::mem::size_of::<DrawVert>(), 4);
59 let buffer = device.create_buffer(&BufferDescriptor {
60 label: Some("Dear ImGui Vertex Buffer"),
61 size: buffer_size as u64,
62 usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
63 mapped_at_creation: false,
64 });
65
66 let host_buffer = vec![0u8; new_size * std::mem::size_of::<DrawVert>()];
68
69 self.vertex_buffer = Some(buffer);
70 self.vertex_buffer_host = Some(host_buffer);
71 self.vertex_buffer_size = new_size;
72 }
73
74 Ok(())
75 }
76
77 pub fn ensure_index_buffer_capacity(
79 &mut self,
80 device: &Device,
81 required_indices: usize,
82 ) -> Result<(), String> {
83 if self.index_buffer.is_none() || self.index_buffer_size < required_indices {
84 let new_size = (required_indices + 10000).max(self.index_buffer_size * 2);
86
87 let buffer_size = align_size(new_size * std::mem::size_of::<DrawIdx>(), 4);
89 let buffer = device.create_buffer(&BufferDescriptor {
90 label: Some("Dear ImGui Index Buffer"),
91 size: buffer_size as u64,
92 usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
93 mapped_at_creation: false,
94 });
95
96 let host_buffer = vec![0u8; new_size * std::mem::size_of::<DrawIdx>()];
98
99 self.index_buffer = Some(buffer);
100 self.index_buffer_host = Some(host_buffer);
101 self.index_buffer_size = new_size;
102 }
103
104 Ok(())
105 }
106
107 pub fn upload_vertex_data(
109 &mut self,
110 queue: &Queue,
111 vertices: &[DrawVert],
112 ) -> Result<(), String> {
113 let vertex_buffer = self
114 .vertex_buffer
115 .as_ref()
116 .ok_or("Vertex buffer not initialized")?;
117
118 let vertex_bytes = unsafe {
120 std::slice::from_raw_parts(
121 vertices.as_ptr() as *const u8,
122 std::mem::size_of_val(vertices),
123 )
124 };
125
126 if let Some(ref mut host_buffer) = self.vertex_buffer_host
128 && vertex_bytes.len() <= host_buffer.len()
129 {
130 host_buffer[..vertex_bytes.len()].copy_from_slice(vertex_bytes);
131 }
132
133 let aligned_size = align_size(vertex_bytes.len(), 4);
135 if aligned_size > vertex_bytes.len() {
136 let mut aligned_data = vertex_bytes.to_vec();
138 aligned_data.resize(aligned_size, 0);
139 queue.write_buffer(vertex_buffer, 0, &aligned_data);
140 } else {
141 queue.write_buffer(vertex_buffer, 0, vertex_bytes);
142 }
143 Ok(())
144 }
145
146 pub fn upload_index_data(&mut self, queue: &Queue, indices: &[DrawIdx]) -> Result<(), String> {
148 let index_buffer = self
149 .index_buffer
150 .as_ref()
151 .ok_or("Index buffer not initialized")?;
152
153 let index_bytes = unsafe {
155 std::slice::from_raw_parts(
156 indices.as_ptr() as *const u8,
157 std::mem::size_of_val(indices),
158 )
159 };
160
161 if let Some(ref mut host_buffer) = self.index_buffer_host
163 && index_bytes.len() <= host_buffer.len()
164 {
165 host_buffer[..index_bytes.len()].copy_from_slice(index_bytes);
166 }
167
168 let aligned_size = align_size(index_bytes.len(), 4);
170 if aligned_size > index_bytes.len() {
171 let mut aligned_data = index_bytes.to_vec();
173 aligned_data.resize(aligned_size, 0);
174 queue.write_buffer(index_buffer, 0, &aligned_data);
175 } else {
176 queue.write_buffer(index_buffer, 0, index_bytes);
177 }
178 Ok(())
179 }
180
181 pub fn vertex_buffer(&self) -> Option<&Buffer> {
183 self.vertex_buffer.as_ref()
184 }
185
186 pub fn index_buffer(&self) -> Option<&Buffer> {
188 self.index_buffer.as_ref()
189 }
190
191 pub fn is_ready(&self) -> bool {
193 self.vertex_buffer.is_some() && self.index_buffer.is_some()
194 }
195
196 pub fn stats(&self) -> FrameResourcesStats {
198 FrameResourcesStats {
199 vertex_buffer_size: self.vertex_buffer_size,
200 index_buffer_size: self.index_buffer_size,
201 vertex_buffer_bytes: self.vertex_buffer_size * std::mem::size_of::<DrawVert>(),
202 index_buffer_bytes: self.index_buffer_size * std::mem::size_of::<DrawIdx>(),
203 }
204 }
205}
206
207impl Default for FrameResources {
208 fn default() -> Self {
209 Self::new()
210 }
211}
212
213#[derive(Debug, Clone)]
215pub struct FrameResourcesStats {
216 pub vertex_buffer_size: usize,
217 pub index_buffer_size: usize,
218 pub vertex_buffer_bytes: usize,
219 pub index_buffer_bytes: usize,
220}