oxihuman_viewer/
draw_command.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
9#[allow(dead_code)]
10pub enum DrawPrimitive {
11 Triangles,
12 Lines,
13 Points,
14 TriangleStrip,
15}
16
17#[derive(Debug, Clone, PartialEq)]
19#[allow(dead_code)]
20pub struct DrawCommand {
21 pub vertex_offset: u32,
22 pub index_offset: u32,
23 pub index_count: u32,
24 pub instance_count: u32,
25 pub pipeline_id: u32,
26 pub sort_key: u64,
27 pub primitive: DrawPrimitive,
28 pub enabled: bool,
29}
30
31impl Default for DrawCommand {
32 fn default() -> Self {
33 Self {
34 vertex_offset: 0,
35 index_offset: 0,
36 index_count: 0,
37 instance_count: 1,
38 pipeline_id: 0,
39 sort_key: 0,
40 primitive: DrawPrimitive::Triangles,
41 enabled: true,
42 }
43 }
44}
45
46#[derive(Debug, Clone, Default)]
48#[allow(dead_code)]
49pub struct DrawCommandRecorder {
50 pub commands: Vec<DrawCommand>,
51 pub max_commands: usize,
52}
53
54#[allow(dead_code)]
56pub fn new_draw_recorder(max_commands: usize) -> DrawCommandRecorder {
57 DrawCommandRecorder {
58 commands: Vec::new(),
59 max_commands,
60 }
61}
62
63#[allow(dead_code)]
65pub fn record_draw(r: &mut DrawCommandRecorder, cmd: DrawCommand) -> bool {
66 if r.commands.len() >= r.max_commands {
67 return false;
68 }
69 r.commands.push(cmd);
70 true
71}
72
73#[allow(dead_code)]
75pub fn clear_commands(r: &mut DrawCommandRecorder) {
76 r.commands.clear();
77}
78
79#[allow(dead_code)]
81pub fn command_count(r: &DrawCommandRecorder) -> usize {
82 r.commands.len()
83}
84
85#[allow(dead_code)]
87pub fn total_index_count(r: &DrawCommandRecorder) -> u32 {
88 r.commands
89 .iter()
90 .filter(|c| c.enabled)
91 .map(|c| c.index_count)
92 .sum()
93}
94
95#[allow(dead_code)]
97pub fn total_instance_count(r: &DrawCommandRecorder) -> u32 {
98 r.commands
99 .iter()
100 .filter(|c| c.enabled)
101 .map(|c| c.instance_count)
102 .sum()
103}
104
105#[allow(dead_code)]
107pub fn sort_commands_ascending(r: &mut DrawCommandRecorder) {
108 r.commands.sort_by_key(|c| c.sort_key);
109}
110
111#[allow(dead_code)]
113pub fn sort_commands_descending(r: &mut DrawCommandRecorder) {
114 r.commands.sort_by_key(|c| std::cmp::Reverse(c.sort_key));
115}
116
117#[allow(dead_code)]
119pub fn group_by_pipeline(r: &mut DrawCommandRecorder) {
120 r.commands.sort_by_key(|c| c.pipeline_id);
121}
122
123#[allow(dead_code)]
125pub fn is_recorder_full(r: &DrawCommandRecorder) -> bool {
126 r.commands.len() >= r.max_commands
127}
128
129#[allow(dead_code)]
131pub fn draw_command_to_json(r: &DrawCommandRecorder) -> String {
132 format!(
133 r#"{{"command_count":{},"total_indices":{}}}"#,
134 r.commands.len(),
135 total_index_count(r)
136 )
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn new_recorder_empty() {
145 let r = new_draw_recorder(100);
146 assert_eq!(command_count(&r), 0);
147 }
148
149 #[test]
150 fn record_returns_true() {
151 let mut r = new_draw_recorder(10);
152 assert!(record_draw(&mut r, DrawCommand::default()));
153 }
154
155 #[test]
156 fn capacity_limit() {
157 let mut r = new_draw_recorder(1);
158 record_draw(&mut r, DrawCommand::default());
159 assert!(!record_draw(&mut r, DrawCommand::default()));
160 }
161
162 #[test]
163 fn clear_empties() {
164 let mut r = new_draw_recorder(10);
165 record_draw(&mut r, DrawCommand::default());
166 clear_commands(&mut r);
167 assert_eq!(command_count(&r), 0);
168 }
169
170 #[test]
171 fn total_index_count_correct() {
172 let mut r = new_draw_recorder(10);
173 record_draw(
174 &mut r,
175 DrawCommand {
176 index_count: 300,
177 ..Default::default()
178 },
179 );
180 record_draw(
181 &mut r,
182 DrawCommand {
183 index_count: 150,
184 ..Default::default()
185 },
186 );
187 assert_eq!(total_index_count(&r), 450);
188 }
189
190 #[test]
191 fn disabled_excluded_from_total() {
192 let mut r = new_draw_recorder(10);
193 record_draw(
194 &mut r,
195 DrawCommand {
196 index_count: 100,
197 enabled: false,
198 ..Default::default()
199 },
200 );
201 assert_eq!(total_index_count(&r), 0);
202 }
203
204 #[test]
205 fn sort_ascending() {
206 let mut r = new_draw_recorder(10);
207 record_draw(
208 &mut r,
209 DrawCommand {
210 sort_key: 5,
211 ..Default::default()
212 },
213 );
214 record_draw(
215 &mut r,
216 DrawCommand {
217 sort_key: 1,
218 ..Default::default()
219 },
220 );
221 sort_commands_ascending(&mut r);
222 assert_eq!(r.commands[0].sort_key, 1);
223 }
224
225 #[test]
226 fn group_by_pipeline_sorts() {
227 let mut r = new_draw_recorder(10);
228 record_draw(
229 &mut r,
230 DrawCommand {
231 pipeline_id: 3,
232 ..Default::default()
233 },
234 );
235 record_draw(
236 &mut r,
237 DrawCommand {
238 pipeline_id: 1,
239 ..Default::default()
240 },
241 );
242 group_by_pipeline(&mut r);
243 assert_eq!(r.commands[0].pipeline_id, 1);
244 }
245
246 #[test]
247 fn is_full_check() {
248 let mut r = new_draw_recorder(1);
249 record_draw(&mut r, DrawCommand::default());
250 assert!(is_recorder_full(&r));
251 }
252
253 #[test]
254 fn json_contains_command_count() {
255 let r = new_draw_recorder(10);
256 assert!(draw_command_to_json(&r).contains("command_count"));
257 }
258}