molgfx_gpu/residency/
command.rs1use std::fmt;
4use thiserror::Error;
5
6#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
8pub struct CommandScratchMetrics {
9 pub commands_recorded: u64,
11 pub peak_commands: usize,
13 pub capacity_stalls: u64,
15 pub host_allocation_events: u64,
17}
18
19#[derive(Clone, Copy, Debug, Error, PartialEq, Eq)]
21#[error("command scratch capacity {capacity} is exhausted")]
22pub struct ScratchFull {
23 pub capacity: usize,
25}
26
27pub struct CommandScratch<C: Copy> {
32 commands: Vec<C>,
33 limit: usize,
34 metrics: CommandScratchMetrics,
35}
36
37impl<C: Copy> CommandScratch<C> {
38 #[must_use]
40 pub fn new(capacity: usize) -> Self {
41 Self {
42 commands: Vec::with_capacity(capacity),
43 limit: capacity,
44 metrics: CommandScratchMetrics {
45 host_allocation_events: u64::from(capacity > 0),
46 ..CommandScratchMetrics::default()
47 },
48 }
49 }
50
51 pub fn clear(&mut self) {
53 self.commands.clear();
54 }
55
56 pub fn push(&mut self, command: C) -> Result<(), ScratchFull> {
62 if self.commands.len() == self.limit {
63 self.metrics.capacity_stalls = self.metrics.capacity_stalls.saturating_add(1);
64 return Err(ScratchFull {
65 capacity: self.limit,
66 });
67 }
68 self.commands.push(command);
69 self.metrics.commands_recorded = self.metrics.commands_recorded.saturating_add(1);
70 self.metrics.peak_commands = self.metrics.peak_commands.max(self.commands.len());
71 Ok(())
72 }
73
74 #[must_use]
76 pub fn as_slice(&self) -> &[C] {
77 &self.commands
78 }
79
80 #[must_use]
82 pub fn as_mut_slice(&mut self) -> &mut [C] {
83 &mut self.commands
84 }
85
86 #[must_use]
88 pub const fn capacity(&self) -> usize {
89 self.limit
90 }
91
92 #[must_use]
94 pub const fn metrics(&self) -> CommandScratchMetrics {
95 self.metrics
96 }
97}
98
99impl<C: Copy + fmt::Debug> fmt::Debug for CommandScratch<C> {
100 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
101 formatter
102 .debug_struct("CommandScratch")
103 .field("commands", &self.commands)
104 .field("limit", &self.limit)
105 .field("metrics", &self.metrics)
106 .finish()
107 }
108}
109
110#[cfg(test)]
111#[path = "command_tests.rs"]
112mod tests;