sdl3/gpu/
buffer.rs

1use crate::{
2    get_error,
3    gpu::{device::WeakDevice, BufferUsageFlags, Device, TransferBufferUsage, VertexInputRate},
4    sys, Error,
5};
6use std::sync::Arc;
7use sys::gpu::{
8    SDL_CreateGPUBuffer, SDL_CreateGPUTransferBuffer, SDL_GPUBuffer, SDL_GPUBufferBinding,
9    SDL_GPUBufferCreateInfo, SDL_GPUBufferRegion, SDL_GPUTransferBuffer,
10    SDL_GPUTransferBufferCreateInfo, SDL_GPUTransferBufferLocation, SDL_GPUTransferBufferUsage,
11    SDL_GPUVertexBufferDescription, SDL_GPUVertexInputRate, SDL_MapGPUTransferBuffer,
12    SDL_ReleaseGPUBuffer, SDL_ReleaseGPUTransferBuffer, SDL_UnmapGPUTransferBuffer,
13};
14
15#[repr(C)]
16#[derive(Default)]
17pub struct BufferBinding {
18    pub(super) inner: SDL_GPUBufferBinding,
19}
20impl BufferBinding {
21    pub fn new() -> Self {
22        Default::default()
23    }
24
25    pub fn with_buffer(mut self, buffer: &Buffer) -> Self {
26        self.inner.buffer = buffer.raw();
27        self
28    }
29
30    pub fn with_offset(mut self, offset: u32) -> Self {
31        self.inner.offset = offset;
32        self
33    }
34}
35
36#[derive(Default)]
37pub struct TransferBufferLocation {
38    pub(super) inner: SDL_GPUTransferBufferLocation,
39}
40impl TransferBufferLocation {
41    pub fn new() -> Self {
42        Default::default()
43    }
44
45    pub fn with_transfer_buffer(mut self, transfer_buffer: &TransferBuffer) -> Self {
46        self.inner.transfer_buffer = transfer_buffer.raw();
47        self
48    }
49
50    pub fn with_offset(mut self, offset: u32) -> Self {
51        self.inner.offset = offset;
52        self
53    }
54}
55
56#[derive(Default)]
57pub struct BufferRegion {
58    pub(super) inner: SDL_GPUBufferRegion,
59}
60impl BufferRegion {
61    pub fn new() -> Self {
62        Default::default()
63    }
64
65    pub fn with_buffer(mut self, buffer: &Buffer) -> Self {
66        self.inner.buffer = buffer.raw();
67        self
68    }
69
70    pub fn with_offset(mut self, offset: u32) -> Self {
71        self.inner.offset = offset;
72        self
73    }
74
75    pub fn with_size(mut self, size: u32) -> Self {
76        self.inner.size = size;
77        self
78    }
79}
80
81#[repr(C)]
82#[derive(Clone, Default)]
83pub struct VertexBufferDescription {
84    inner: SDL_GPUVertexBufferDescription,
85}
86impl VertexBufferDescription {
87    pub fn new() -> Self {
88        Default::default()
89    }
90
91    pub fn with_slot(mut self, value: u32) -> Self {
92        self.inner.slot = value;
93        self
94    }
95
96    pub fn with_pitch(mut self, value: u32) -> Self {
97        self.inner.pitch = value;
98        self
99    }
100
101    pub fn with_input_rate(mut self, value: VertexInputRate) -> Self {
102        self.inner.input_rate = SDL_GPUVertexInputRate(value as i32);
103        self
104    }
105
106    pub fn with_instance_step_rate(mut self, value: u32) -> Self {
107        self.inner.instance_step_rate = value;
108        self
109    }
110}
111
112/// Manages the raw `SDL_GPUBuffer` pointer and releases it on drop
113struct BufferContainer {
114    raw: *mut SDL_GPUBuffer,
115    device: WeakDevice,
116}
117impl Drop for BufferContainer {
118    #[doc(alias = "SDL_ReleaseGPUBuffer")]
119    fn drop(&mut self) {
120        if let Some(device) = self.device.upgrade() {
121            unsafe {
122                SDL_ReleaseGPUBuffer(device.raw(), self.raw);
123            }
124        }
125    }
126}
127
128#[doc(alias = "SDL_GPUBuffer")]
129#[derive(Clone)]
130pub struct Buffer {
131    inner: Arc<BufferContainer>,
132    len: u32,
133}
134impl Buffer {
135    /// Yields the raw SDL_GPUBuffer pointer.
136    #[inline]
137    pub fn raw(&self) -> *mut SDL_GPUBuffer {
138        self.inner.raw
139    }
140
141    /// The length of this buffer in bytes.
142    pub fn len(&self) -> u32 {
143        self.len
144    }
145}
146
147pub struct BufferBuilder<'a> {
148    device: &'a Device,
149    inner: SDL_GPUBufferCreateInfo,
150}
151impl<'a> BufferBuilder<'a> {
152    pub(super) fn new(device: &'a Device) -> Self {
153        Self {
154            device,
155            inner: Default::default(),
156        }
157    }
158
159    pub fn with_usage(mut self, value: BufferUsageFlags) -> Self {
160        self.inner.usage = value as u32;
161        self
162    }
163
164    pub fn with_size(mut self, value: u32) -> Self {
165        self.inner.size = value;
166        self
167    }
168
169    pub fn build(self) -> Result<Buffer, Error> {
170        let raw_buffer = unsafe { SDL_CreateGPUBuffer(self.device.raw(), &self.inner) };
171        if raw_buffer.is_null() {
172            Err(get_error())
173        } else {
174            Ok(Buffer {
175                len: self.inner.size,
176                inner: Arc::new(BufferContainer {
177                    raw: raw_buffer,
178                    device: self.device.weak(),
179                }),
180            })
181        }
182    }
183}
184
185/// Mapped memory for a transfer buffer.
186pub struct BufferMemMap<'a, T> {
187    device: &'a Device,
188    transfer_buffer: &'a TransferBuffer,
189    mem: *mut T,
190}
191
192impl<'a, T> BufferMemMap<'a, T>
193where
194    T: Copy,
195{
196    /// Access the memory as a readonly slice.
197    pub fn mem(&self) -> &[T] {
198        let count = self.transfer_buffer.len() as usize / std::mem::size_of::<T>();
199        unsafe { std::slice::from_raw_parts(self.mem, count) }
200    }
201
202    /// Access the memory as a mutable slice.
203    pub fn mem_mut(&mut self) -> &mut [T] {
204        let count = self.transfer_buffer.len() as usize / std::mem::size_of::<T>();
205        unsafe { std::slice::from_raw_parts_mut(self.mem, count) }
206    }
207
208    #[doc(alias = "SDL_UnmapGPUTransferBuffer")]
209    pub fn unmap(self) {
210        unsafe { SDL_UnmapGPUTransferBuffer(self.device.raw(), self.transfer_buffer.raw()) };
211    }
212}
213
214/// Manages the raw `SDL_GPUTransferBuffer` pointer and releases it on drop
215struct TransferBufferContainer {
216    raw: *mut SDL_GPUTransferBuffer,
217    device: WeakDevice,
218}
219impl Drop for TransferBufferContainer {
220    #[doc(alias = "SDL_ReleaseGPUTransferBuffer")]
221    fn drop(&mut self) {
222        if let Some(device) = self.device.upgrade() {
223            unsafe {
224                SDL_ReleaseGPUTransferBuffer(device.raw(), self.raw);
225            }
226        }
227    }
228}
229
230#[derive(Clone)]
231pub struct TransferBuffer {
232    inner: Arc<TransferBufferContainer>,
233    len: u32,
234}
235impl TransferBuffer {
236    #[inline]
237    pub fn raw(&self) -> *mut SDL_GPUTransferBuffer {
238        self.inner.raw
239    }
240
241    #[doc(alias = "SDL_MapGPUTransferBuffer")]
242    pub fn map<'a, T: Copy>(&'a self, device: &'a Device, cycle: bool) -> BufferMemMap<'a, T> {
243        BufferMemMap {
244            device,
245            transfer_buffer: self,
246            mem: unsafe { SDL_MapGPUTransferBuffer(device.raw(), self.raw(), cycle) } as *mut T,
247        }
248    }
249
250    /// The length of this buffer in bytes.
251    pub fn len(&self) -> u32 {
252        self.len
253    }
254}
255
256pub struct TransferBufferBuilder<'a> {
257    device: &'a Device,
258    inner: SDL_GPUTransferBufferCreateInfo,
259}
260impl<'a> TransferBufferBuilder<'a> {
261    pub(super) fn new(device: &'a Device) -> Self {
262        Self {
263            device,
264            inner: Default::default(),
265        }
266    }
267
268    /// How the buffer will be used.
269    pub fn with_usage(mut self, value: TransferBufferUsage) -> Self {
270        self.inner.usage = SDL_GPUTransferBufferUsage(value as i32);
271        self
272    }
273
274    /// Desired size of the buffer in bytes.
275    pub fn with_size(mut self, value: u32) -> Self {
276        self.inner.size = value;
277        self
278    }
279
280    pub fn build(self) -> Result<TransferBuffer, Error> {
281        let raw_buffer = unsafe { SDL_CreateGPUTransferBuffer(self.device.raw(), &self.inner) };
282        if raw_buffer.is_null() {
283            Err(get_error())
284        } else {
285            Ok(TransferBuffer {
286                inner: Arc::new(TransferBufferContainer {
287                    raw: raw_buffer,
288                    device: self.device.weak(),
289                }),
290                len: self.inner.size,
291            })
292        }
293    }
294}