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
112struct 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 #[inline]
137 pub fn raw(&self) -> *mut SDL_GPUBuffer {
138 self.inner.raw
139 }
140
141 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
185pub 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 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 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
214struct 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 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 pub fn with_usage(mut self, value: TransferBufferUsage) -> Self {
270 self.inner.usage = SDL_GPUTransferBufferUsage(value as i32);
271 self
272 }
273
274 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}