gpu_allocator/allocator/dedicated_block_allocator/
mod.rs1#![deny(unsafe_code, clippy::unwrap_used)]
2#[cfg(feature = "std")]
3use alloc::sync::Arc;
4use alloc::{
5 borrow::ToOwned,
6 string::{String, ToString},
7 vec::Vec,
8};
9#[cfg(feature = "std")]
10use std::backtrace::Backtrace;
11
12use log::{log, Level};
13
14#[cfg(feature = "visualizer")]
15pub(crate) mod visualizer;
16
17use super::{AllocationReport, AllocationType, SubAllocator, SubAllocatorBase};
18use crate::{AllocationError, Result};
19
20#[derive(Debug)]
21pub(crate) struct DedicatedBlockAllocator {
22 size: u64,
23 allocated: u64,
24 name: Option<String>,
26 #[cfg(feature = "std")]
27 backtrace: Arc<Backtrace>,
28}
29
30impl DedicatedBlockAllocator {
31 pub(crate) fn new(size: u64) -> Self {
32 Self {
33 size,
34 allocated: 0,
35 name: None,
36 #[cfg(feature = "std")]
37 backtrace: Arc::new(Backtrace::disabled()),
38 }
39 }
40}
41
42impl SubAllocatorBase for DedicatedBlockAllocator {}
43impl SubAllocator for DedicatedBlockAllocator {
44 fn allocate(
45 &mut self,
46 size: u64,
47 _alignment: u64,
48 _allocation_type: AllocationType,
49 _granularity: u64,
50 name: &str,
51 #[cfg(feature = "std")] backtrace: Arc<Backtrace>,
52 ) -> Result<(u64, core::num::NonZeroU64)> {
53 if self.allocated != 0 {
54 return Err(AllocationError::OutOfMemory);
55 }
56
57 if self.size != size {
58 return Err(AllocationError::Internal(
59 "DedicatedBlockAllocator size must match allocation size.".into(),
60 ));
61 }
62
63 self.allocated = size;
64 self.name = Some(name.to_string());
65 #[cfg(feature = "std")]
66 {
67 self.backtrace = backtrace;
68 }
69
70 #[allow(clippy::unwrap_used)]
71 let dummy_id = core::num::NonZeroU64::new(1).unwrap();
72 Ok((0, dummy_id))
73 }
74
75 fn free(&mut self, chunk_id: Option<core::num::NonZeroU64>) -> Result<()> {
76 if chunk_id != core::num::NonZeroU64::new(1) {
77 Err(AllocationError::Internal("Chunk ID must be 1.".into()))
78 } else {
79 self.allocated = 0;
80 Ok(())
81 }
82 }
83
84 fn rename_allocation(
85 &mut self,
86 chunk_id: Option<core::num::NonZeroU64>,
87 name: &str,
88 ) -> Result<()> {
89 if chunk_id != core::num::NonZeroU64::new(1) {
90 Err(AllocationError::Internal("Chunk ID must be 1.".into()))
91 } else {
92 self.name = Some(name.into());
93 Ok(())
94 }
95 }
96
97 fn report_memory_leaks(
98 &self,
99 log_level: Level,
100 memory_type_index: usize,
101 memory_block_index: usize,
102 ) {
103 let empty = "".to_string();
104 let name = self.name.as_ref().unwrap_or(&empty);
105 let backtrace_info;
106 #[cfg(feature = "std")]
107 {
108 backtrace_info = format!(
110 ",
111 backtrace: {}",
112 self.backtrace
113 )
114 }
115 #[cfg(not(feature = "std"))]
116 {
117 backtrace_info = ""
118 }
119
120 log!(
121 log_level,
122 r#"leak detected: {{
123 memory type: {}
124 memory block: {}
125 dedicated allocation: {{
126 size: 0x{:x},
127 name: {}{backtrace_info}
128 }}
129}}"#,
130 memory_type_index,
131 memory_block_index,
132 self.size,
133 name,
134 );
135 }
136
137 fn report_allocations(&self) -> Vec<AllocationReport> {
138 vec![AllocationReport {
139 name: self
140 .name
141 .clone()
142 .unwrap_or_else(|| "<Unnamed Dedicated allocation>".to_owned()),
143 offset: 0,
144 size: self.size,
145 #[cfg(feature = "visualizer")]
146 backtrace: self.backtrace.clone(),
147 }]
148 }
149
150 fn allocated(&self) -> u64 {
151 self.allocated
152 }
153
154 fn supports_general_allocations(&self) -> bool {
155 false
156 }
157}