1use serde::{Deserialize, Serialize};
2use std::fmt;
3use std::sync::Arc;
4use std::sync::atomic::{AtomicU64, Ordering};
5
6use crate::{GpuFormat, GpuMemoryLocation, GpuUsage};
7
8static NEXT_BUFFER_ID: AtomicU64 = AtomicU64::new(1);
9static NEXT_IMAGE_ID: AtomicU64 = AtomicU64::new(1);
10
11#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
19pub struct GpuBufferId(pub u64);
20
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
29pub struct GpuImageId(pub u64);
30
31impl fmt::Display for GpuBufferId {
32 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
33 write!(f, "buf-{}", self.0)
34 }
35}
36
37impl fmt::Display for GpuImageId {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 write!(f, "img-{}", self.0)
40 }
41}
42
43fn next_buffer_id() -> GpuBufferId {
44 GpuBufferId(NEXT_BUFFER_ID.fetch_add(1, Ordering::Relaxed))
45}
46
47fn next_image_id() -> GpuImageId {
48 GpuImageId(NEXT_IMAGE_ID.fetch_add(1, Ordering::Relaxed))
49}
50
51pub(crate) trait GpuDropToken: Send + Sync + fmt::Debug {}
52
53impl<T: Send + Sync + fmt::Debug> GpuDropToken for T {}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
63pub struct GpuBufferHandle {
64 pub id: GpuBufferId,
65 pub size_bytes: u64,
66 pub location: GpuMemoryLocation,
67 pub usage: GpuUsage,
68 pub label: Option<String>,
69 #[serde(skip)]
70 pub(crate) drop_token: Option<Arc<dyn GpuDropToken>>,
71}
72
73impl GpuBufferHandle {
74 pub fn new(size_bytes: u64, location: GpuMemoryLocation, usage: GpuUsage) -> Self {
76 Self {
77 id: next_buffer_id(),
78 size_bytes,
79 location,
80 usage,
81 label: None,
82 drop_token: None,
83 }
84 }
85
86 pub fn with_label(mut self, label: impl Into<String>) -> Self {
88 self.label = Some(label.into());
89 self
90 }
91}
92
93impl Drop for GpuBufferHandle {
94 fn drop(&mut self) {
95 let _ = self.drop_token.take();
98 }
99}
100
101impl PartialEq for GpuBufferHandle {
102 fn eq(&self, other: &Self) -> bool {
103 self.id == other.id
104 && self.size_bytes == other.size_bytes
105 && self.location == other.location
106 && self.usage == other.usage
107 && self.label == other.label
108 }
109}
110
111impl Eq for GpuBufferHandle {}
112
113#[derive(Debug, Clone, Serialize, Deserialize)]
121pub struct GpuImageHandle {
122 pub id: GpuImageId,
123 pub format: GpuFormat,
124 pub width: u32,
125 pub height: u32,
126 pub location: GpuMemoryLocation,
127 pub usage: GpuUsage,
128 pub label: Option<String>,
129 #[serde(skip)]
130 pub(crate) drop_token: Option<Arc<dyn GpuDropToken>>,
131}
132
133impl GpuImageHandle {
134 pub fn new(
136 format: GpuFormat,
137 width: u32,
138 height: u32,
139 location: GpuMemoryLocation,
140 usage: GpuUsage,
141 ) -> Self {
142 Self {
143 id: next_image_id(),
144 format,
145 width,
146 height,
147 location,
148 usage,
149 label: None,
150 drop_token: None,
151 }
152 }
153
154 pub fn with_label(mut self, label: impl Into<String>) -> Self {
156 self.label = Some(label.into());
157 self
158 }
159}
160
161impl Drop for GpuImageHandle {
162 fn drop(&mut self) {
163 let _ = self.drop_token.take();
166 }
167}
168
169impl PartialEq for GpuImageHandle {
170 fn eq(&self, other: &Self) -> bool {
171 self.id == other.id
172 && self.format == other.format
173 && self.width == other.width
174 && self.height == other.height
175 && self.location == other.location
176 && self.usage == other.usage
177 && self.label == other.label
178 }
179}
180
181impl Eq for GpuImageHandle {}