dear_imgui_wgpu/
frame_resources.rs1use crate::{RendererError, RendererResult};
7use dear_imgui_rs::render::{DrawIdx, DrawVert};
8use wgpu::*;
9
10fn align_size(size: usize, alignment: usize) -> usize {
13 (size + alignment - 1) & !(alignment - 1)
14}
15
16pub struct FrameResources {
21 pub vertex_buffer: Option<Buffer>,
23 pub index_buffer: Option<Buffer>,
25 pub vertex_buffer_host: Option<Vec<u8>>,
27 pub index_buffer_host: Option<Vec<u8>>,
29 pub vertex_buffer_size: usize,
31 pub index_buffer_size: usize,
33}
34
35impl FrameResources {
36 pub fn new() -> Self {
38 Self {
39 vertex_buffer: None,
40 index_buffer: None,
41 vertex_buffer_host: None,
42 index_buffer_host: None,
43 vertex_buffer_size: 0,
44 index_buffer_size: 0,
45 }
46 }
47
48 pub fn ensure_vertex_buffer_capacity(
50 &mut self,
51 device: &Device,
52 required_vertices: usize,
53 ) -> RendererResult<()> {
54 if self.vertex_buffer.is_none() || self.vertex_buffer_size < required_vertices {
55 let new_size = (required_vertices + 5000).max(self.vertex_buffer_size * 2);
57
58 let buffer_size = align_size(new_size * std::mem::size_of::<DrawVert>(), 4);
60 let buffer = device.create_buffer(&BufferDescriptor {
61 label: Some("Dear ImGui Vertex Buffer"),
62 size: buffer_size as u64,
63 usage: BufferUsages::VERTEX | BufferUsages::COPY_DST,
64 mapped_at_creation: false,
65 });
66
67 let host_buffer = vec![0u8; new_size * std::mem::size_of::<DrawVert>()];
69
70 self.vertex_buffer = Some(buffer);
71 self.vertex_buffer_host = Some(host_buffer);
72 self.vertex_buffer_size = new_size;
73 }
74
75 Ok(())
76 }
77
78 pub fn ensure_index_buffer_capacity(
80 &mut self,
81 device: &Device,
82 required_indices: usize,
83 ) -> RendererResult<()> {
84 if self.index_buffer.is_none() || self.index_buffer_size < required_indices {
85 let new_size = (required_indices + 10000).max(self.index_buffer_size * 2);
87
88 let buffer_size = align_size(new_size * std::mem::size_of::<DrawIdx>(), 4);
90 let buffer = device.create_buffer(&BufferDescriptor {
91 label: Some("Dear ImGui Index Buffer"),
92 size: buffer_size as u64,
93 usage: BufferUsages::INDEX | BufferUsages::COPY_DST,
94 mapped_at_creation: false,
95 });
96
97 let host_buffer = vec![0u8; new_size * std::mem::size_of::<DrawIdx>()];
99
100 self.index_buffer = Some(buffer);
101 self.index_buffer_host = Some(host_buffer);
102 self.index_buffer_size = new_size;
103 }
104
105 Ok(())
106 }
107
108 pub fn upload_vertex_data(
110 &mut self,
111 queue: &Queue,
112 vertices: &[DrawVert],
113 ) -> RendererResult<()> {
114 let vertex_buffer = self.vertex_buffer.as_ref().ok_or_else(|| {
115 RendererError::InvalidRenderState("Vertex buffer not initialized".to_string())
116 })?;
117
118 let required_bytes = std::mem::size_of_val(vertices);
119 let aligned_size = align_size(required_bytes, 4);
120
121 let host_buffer = self.vertex_buffer_host.as_mut().ok_or_else(|| {
122 RendererError::InvalidRenderState("Vertex host buffer not initialized".to_string())
123 })?;
124 if aligned_size > host_buffer.len() {
125 return Err(RendererError::InvalidRenderState(
126 "Vertex host buffer capacity is too small".to_string(),
127 ));
128 }
129
130 host_buffer[..aligned_size].fill(0);
133 const VERT_STRIDE: usize = std::mem::size_of::<DrawVert>();
134 for (i, v) in vertices.iter().enumerate() {
135 let base = i * VERT_STRIDE;
136 host_buffer[base..base + 4].copy_from_slice(&v.pos[0].to_ne_bytes());
137 host_buffer[base + 4..base + 8].copy_from_slice(&v.pos[1].to_ne_bytes());
138 host_buffer[base + 8..base + 12].copy_from_slice(&v.uv[0].to_ne_bytes());
139 host_buffer[base + 12..base + 16].copy_from_slice(&v.uv[1].to_ne_bytes());
140 host_buffer[base + 16..base + 20].copy_from_slice(&v.col.to_ne_bytes());
141 }
142
143 queue.write_buffer(vertex_buffer, 0, &host_buffer[..aligned_size]);
145 Ok(())
146 }
147
148 pub fn upload_index_data(&mut self, queue: &Queue, indices: &[DrawIdx]) -> RendererResult<()> {
150 let index_buffer = self.index_buffer.as_ref().ok_or_else(|| {
151 RendererError::InvalidRenderState("Index buffer not initialized".to_string())
152 })?;
153
154 let required_bytes = std::mem::size_of_val(indices);
155 let aligned_size = align_size(required_bytes, 4);
156
157 let host_buffer = self.index_buffer_host.as_mut().ok_or_else(|| {
158 RendererError::InvalidRenderState("Index host buffer not initialized".to_string())
159 })?;
160 if aligned_size > host_buffer.len() {
161 return Err(RendererError::InvalidRenderState(
162 "Index host buffer capacity is too small".to_string(),
163 ));
164 }
165
166 host_buffer[..aligned_size].fill(0);
167 for (i, &idx) in indices.iter().enumerate() {
168 let bytes = idx.to_ne_bytes();
169 let base = i * std::mem::size_of::<DrawIdx>();
170 host_buffer[base..base + 2].copy_from_slice(&bytes);
171 }
172
173 queue.write_buffer(index_buffer, 0, &host_buffer[..aligned_size]);
175 Ok(())
176 }
177
178 pub fn vertex_buffer(&self) -> Option<&Buffer> {
180 self.vertex_buffer.as_ref()
181 }
182
183 pub fn index_buffer(&self) -> Option<&Buffer> {
185 self.index_buffer.as_ref()
186 }
187
188 pub fn is_ready(&self) -> bool {
190 self.vertex_buffer.is_some() && self.index_buffer.is_some()
191 }
192
193 pub fn stats(&self) -> FrameResourcesStats {
195 FrameResourcesStats {
196 vertex_buffer_size: self.vertex_buffer_size,
197 index_buffer_size: self.index_buffer_size,
198 vertex_buffer_bytes: self.vertex_buffer_size * std::mem::size_of::<DrawVert>(),
199 index_buffer_bytes: self.index_buffer_size * std::mem::size_of::<DrawIdx>(),
200 }
201 }
202}
203
204impl Default for FrameResources {
205 fn default() -> Self {
206 Self::new()
207 }
208}
209
210#[derive(Debug, Clone)]
212pub struct FrameResourcesStats {
213 pub vertex_buffer_size: usize,
214 pub index_buffer_size: usize,
215 pub vertex_buffer_bytes: usize,
216 pub index_buffer_bytes: usize,
217}