rafx_api/
buffer.rs

1#[cfg(feature = "rafx-dx12")]
2use crate::dx12::RafxBufferDx12;
3#[cfg(any(
4    feature = "rafx-empty",
5    not(any(
6        feature = "rafx-dx12",
7        feature = "rafx-metal",
8        feature = "rafx-vulkan",
9        feature = "rafx-gles2",
10        feature = "rafx-gles3"
11    ))
12))]
13use crate::empty::RafxBufferEmpty;
14#[cfg(feature = "rafx-gles2")]
15use crate::gles2::RafxBufferGles2;
16#[cfg(feature = "rafx-gles3")]
17use crate::gles3::RafxBufferGles3;
18#[cfg(feature = "rafx-metal")]
19use crate::metal::RafxBufferMetal;
20#[cfg(feature = "rafx-vulkan")]
21use crate::vulkan::RafxBufferVulkan;
22use crate::{RafxBufferDef, RafxResult};
23
24/// Memory that can be accessed by the rendering API. It may reside in CPU or GPU memory.
25///
26/// Buffers must not be dropped if they are in use by the GPU.
27#[derive(Debug)]
28pub enum RafxBuffer {
29    #[cfg(feature = "rafx-dx12")]
30    Dx12(RafxBufferDx12),
31    #[cfg(feature = "rafx-vulkan")]
32    Vk(RafxBufferVulkan),
33    #[cfg(feature = "rafx-metal")]
34    Metal(RafxBufferMetal),
35    #[cfg(feature = "rafx-gles2")]
36    Gles2(RafxBufferGles2),
37    #[cfg(feature = "rafx-gles3")]
38    Gles3(RafxBufferGles3),
39    #[cfg(any(
40        feature = "rafx-empty",
41        not(any(
42            feature = "rafx-dx12",
43            feature = "rafx-metal",
44            feature = "rafx-vulkan",
45            feature = "rafx-gles2",
46            feature = "rafx-gles3"
47        ))
48    ))]
49    Empty(RafxBufferEmpty),
50}
51
52impl RafxBuffer {
53    /// Copy all the data in the given slice into the buffer. This function will fail if the buffer
54    /// is not writable by the CPU. This function will assert/panic if the buffer is too small to
55    /// hold the data.
56    pub fn copy_to_host_visible_buffer<T: Copy>(
57        &self,
58        data: &[T],
59    ) -> RafxResult<()> {
60        match self {
61            #[cfg(feature = "rafx-dx12")]
62            RafxBuffer::Dx12(inner) => inner.copy_to_host_visible_buffer(data),
63            #[cfg(feature = "rafx-vulkan")]
64            RafxBuffer::Vk(inner) => inner.copy_to_host_visible_buffer(data),
65            #[cfg(feature = "rafx-metal")]
66            RafxBuffer::Metal(inner) => inner.copy_to_host_visible_buffer(data),
67            #[cfg(feature = "rafx-gles2")]
68            RafxBuffer::Gles2(inner) => inner.copy_to_host_visible_buffer(data),
69            #[cfg(feature = "rafx-gles3")]
70            RafxBuffer::Gles3(inner) => inner.copy_to_host_visible_buffer(data),
71            #[cfg(any(
72                feature = "rafx-empty",
73                not(any(
74                    feature = "rafx-dx12",
75                    feature = "rafx-metal",
76                    feature = "rafx-vulkan",
77                    feature = "rafx-gles2",
78                    feature = "rafx-gles3"
79                ))
80            ))]
81            RafxBuffer::Empty(inner) => inner.copy_to_host_visible_buffer(data),
82        }
83    }
84
85    /// Copy all the data in the given slice into the buffer with a given offset. The offset is in
86    /// bytes. This function will assert/panic if the size of the buffer <= size of data + offset
87    pub fn copy_to_host_visible_buffer_with_offset<T: Copy>(
88        &self,
89        data: &[T],
90        buffer_byte_offset: u64,
91    ) -> RafxResult<()> {
92        match self {
93            #[cfg(feature = "rafx-dx12")]
94            RafxBuffer::Dx12(inner) => {
95                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
96            }
97            #[cfg(feature = "rafx-vulkan")]
98            RafxBuffer::Vk(inner) => {
99                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
100            }
101            #[cfg(feature = "rafx-metal")]
102            RafxBuffer::Metal(inner) => {
103                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
104            }
105            #[cfg(feature = "rafx-gles2")]
106            RafxBuffer::Gles2(inner) => {
107                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
108            }
109            #[cfg(feature = "rafx-gles3")]
110            RafxBuffer::Gles3(inner) => {
111                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
112            }
113            #[cfg(any(
114                feature = "rafx-empty",
115                not(any(
116                    feature = "rafx-dx12",
117                    feature = "rafx-metal",
118                    feature = "rafx-vulkan",
119                    feature = "rafx-gles2",
120                    feature = "rafx-gles3"
121                ))
122            ))]
123            RafxBuffer::Empty(inner) => {
124                inner.copy_to_host_visible_buffer_with_offset(data, buffer_byte_offset)
125            }
126        }
127    }
128
129    /// Return the definition used to create the buffer
130    pub fn buffer_def(&self) -> &RafxBufferDef {
131        match self {
132            #[cfg(feature = "rafx-dx12")]
133            RafxBuffer::Dx12(inner) => inner.buffer_def(),
134            #[cfg(feature = "rafx-vulkan")]
135            RafxBuffer::Vk(inner) => inner.buffer_def(),
136            #[cfg(feature = "rafx-metal")]
137            RafxBuffer::Metal(inner) => inner.buffer_def(),
138            #[cfg(feature = "rafx-gles2")]
139            RafxBuffer::Gles2(inner) => inner.buffer_def(),
140            #[cfg(feature = "rafx-gles3")]
141            RafxBuffer::Gles3(inner) => inner.buffer_def(),
142            #[cfg(any(
143                feature = "rafx-empty",
144                not(any(
145                    feature = "rafx-dx12",
146                    feature = "rafx-metal",
147                    feature = "rafx-vulkan",
148                    feature = "rafx-gles2",
149                    feature = "rafx-gles3"
150                ))
151            ))]
152            RafxBuffer::Empty(inner) => inner.buffer_def(),
153        }
154    }
155
156    /// Map the contents of the buffer into CPU memory. This function will fail if the buffer is not
157    /// possible to map into CPU memory (i.e. it's GPU-only).
158    ///
159    /// The mappings are "ref-counted". Repeated calls to map the same buffer are permitted and the
160    /// buffer will remain mapped until an equal number of calls to unmap_buffer are made.
161    ///
162    /// Generally speaking, keeping a buffer mapped for its entire lifetime is acceptable.
163    pub fn map_buffer(&self) -> RafxResult<*mut u8> {
164        match self {
165            #[cfg(feature = "rafx-dx12")]
166            RafxBuffer::Dx12(inner) => inner.map_buffer(),
167            #[cfg(feature = "rafx-vulkan")]
168            RafxBuffer::Vk(inner) => inner.map_buffer(),
169            #[cfg(feature = "rafx-metal")]
170            RafxBuffer::Metal(inner) => inner.map_buffer(),
171            #[cfg(feature = "rafx-gles2")]
172            RafxBuffer::Gles2(inner) => inner.map_buffer(),
173            #[cfg(feature = "rafx-gles3")]
174            RafxBuffer::Gles3(inner) => inner.map_buffer(),
175            #[cfg(any(
176                feature = "rafx-empty",
177                not(any(
178                    feature = "rafx-dx12",
179                    feature = "rafx-metal",
180                    feature = "rafx-vulkan",
181                    feature = "rafx-gles2",
182                    feature = "rafx-gles3"
183                ))
184            ))]
185            RafxBuffer::Empty(inner) => inner.map_buffer(),
186        }
187    }
188
189    /// Unmap the contents of the buffer from CPU memory. This function will fail if the buffer is
190    /// not possible to map into CPU memory (i.e. it's GPU-only). It will also fail if the buffer
191    /// is not currently mapped.
192    ///
193    /// The mappings are "ref-counted". Repeated calls to map the same buffer are permitted and the
194    /// buffer will remain mapped until an equal number of calls to unmap_buffer are made.
195    pub fn unmap_buffer(&self) -> RafxResult<()> {
196        match self {
197            #[cfg(feature = "rafx-dx12")]
198            RafxBuffer::Dx12(inner) => inner.unmap_buffer(),
199            #[cfg(feature = "rafx-vulkan")]
200            RafxBuffer::Vk(inner) => inner.unmap_buffer(),
201            #[cfg(feature = "rafx-metal")]
202            RafxBuffer::Metal(inner) => inner.unmap_buffer(),
203            #[cfg(feature = "rafx-gles2")]
204            RafxBuffer::Gles2(inner) => inner.unmap_buffer(),
205            #[cfg(feature = "rafx-gles3")]
206            RafxBuffer::Gles3(inner) => inner.unmap_buffer(),
207            #[cfg(any(
208                feature = "rafx-empty",
209                not(any(
210                    feature = "rafx-dx12",
211                    feature = "rafx-metal",
212                    feature = "rafx-vulkan",
213                    feature = "rafx-gles2",
214                    feature = "rafx-gles3"
215                ))
216            ))]
217            RafxBuffer::Empty(inner) => inner.unmap_buffer(),
218        }
219    }
220
221    /// Obtain a pointer to the mapped memory. If the buffer is not mapped, None is returned.
222    pub fn mapped_memory(&self) -> Option<*mut u8> {
223        match self {
224            #[cfg(feature = "rafx-dx12")]
225            RafxBuffer::Dx12(inner) => inner.mapped_memory(),
226            #[cfg(feature = "rafx-vulkan")]
227            RafxBuffer::Vk(inner) => inner.mapped_memory(),
228            #[cfg(feature = "rafx-metal")]
229            RafxBuffer::Metal(inner) => inner.mapped_memory(),
230            #[cfg(feature = "rafx-gles2")]
231            RafxBuffer::Gles2(inner) => inner.mapped_memory(),
232            #[cfg(feature = "rafx-gles3")]
233            RafxBuffer::Gles3(inner) => inner.mapped_memory(),
234            #[cfg(any(
235                feature = "rafx-empty",
236                not(any(
237                    feature = "rafx-dx12",
238                    feature = "rafx-metal",
239                    feature = "rafx-vulkan",
240                    feature = "rafx-gles2",
241                    feature = "rafx-gles3"
242                ))
243            ))]
244            RafxBuffer::Empty(inner) => inner.mapped_memory(),
245        }
246    }
247
248    /// Sets a name for this buffer. This is useful for debugging, graphics debuggers/profilers such
249    /// as nsight graphics or renderdoc will display this buffer with the given name in the list of resources.
250    pub fn set_debug_name(
251        &self,
252        _name: impl AsRef<str>,
253    ) {
254        match self {
255            #[cfg(feature = "rafx-dx12")]
256            RafxBuffer::Dx12(inner) => inner.set_debug_name(_name),
257            #[cfg(feature = "rafx-vulkan")]
258            RafxBuffer::Vk(inner) => inner.set_debug_name(_name),
259            #[cfg(feature = "rafx-metal")]
260            RafxBuffer::Metal(inner) => inner.set_debug_name(_name),
261            #[cfg(feature = "rafx-gles2")]
262            RafxBuffer::Gles2(_) => {}
263            #[cfg(feature = "rafx-gles3")]
264            RafxBuffer::Gles3(_) => {}
265            #[cfg(any(
266                feature = "rafx-empty",
267                not(any(
268                    feature = "rafx-dx12",
269                    feature = "rafx-metal",
270                    feature = "rafx-vulkan",
271                    feature = "rafx-gles2",
272                    feature = "rafx-gles3"
273                ))
274            ))]
275            RafxBuffer::Empty(inner) => inner.set_debug_name(_name),
276        }
277    }
278
279    /// Get the underlying dx12 API object. This provides access to any internally created
280    /// vulkan objects.
281    #[cfg(feature = "rafx-dx12")]
282    pub fn dx12_buffer(&self) -> Option<&RafxBufferDx12> {
283        match self {
284            #[cfg(feature = "rafx-dx12")]
285            RafxBuffer::Dx12(inner) => Some(inner),
286            #[cfg(feature = "rafx-vulkan")]
287            RafxBuffer::Vk(_) => None,
288            #[cfg(feature = "rafx-metal")]
289            RafxBuffer::Metal(_) => None,
290            #[cfg(feature = "rafx-gles2")]
291            RafxBuffer::Gles2(_) => None,
292            #[cfg(feature = "rafx-gles3")]
293            RafxBuffer::Gles3(_) => None,
294            #[cfg(any(
295                feature = "rafx-empty",
296                not(any(
297                    feature = "rafx-dx12",
298                    feature = "rafx-metal",
299                    feature = "rafx-vulkan",
300                    feature = "rafx-gles2",
301                    feature = "rafx-gles3"
302                ))
303            ))]
304            RafxBuffer::Empty(_) => None,
305        }
306    }
307
308    /// Get the underlying vulkan API object. This provides access to any internally created
309    /// vulkan objects.
310    #[cfg(feature = "rafx-vulkan")]
311    pub fn vk_buffer(&self) -> Option<&RafxBufferVulkan> {
312        match self {
313            #[cfg(feature = "rafx-dx12")]
314            RafxBuffer::Dx12(_) => None,
315            #[cfg(feature = "rafx-vulkan")]
316            RafxBuffer::Vk(inner) => Some(inner),
317            #[cfg(feature = "rafx-metal")]
318            RafxBuffer::Metal(_) => None,
319            #[cfg(feature = "rafx-gles2")]
320            RafxBuffer::Gles2(_) => None,
321            #[cfg(feature = "rafx-gles3")]
322            RafxBuffer::Gles3(_) => None,
323            #[cfg(any(
324                feature = "rafx-empty",
325                not(any(
326                    feature = "rafx-dx12",
327                    feature = "rafx-metal",
328                    feature = "rafx-vulkan",
329                    feature = "rafx-gles2",
330                    feature = "rafx-gles3"
331                ))
332            ))]
333            RafxBuffer::Empty(_) => None,
334        }
335    }
336
337    /// Get the underlying metal API object. This provides access to any internally created
338    /// metal objects.
339    #[cfg(feature = "rafx-metal")]
340    pub fn metal_buffer(&self) -> Option<&RafxBufferMetal> {
341        match self {
342            #[cfg(feature = "rafx-dx12")]
343            RafxBuffer::Dx12(_) => None,
344            #[cfg(feature = "rafx-vulkan")]
345            RafxBuffer::Vk(_) => None,
346            #[cfg(feature = "rafx-metal")]
347            RafxBuffer::Metal(inner) => Some(inner),
348            #[cfg(feature = "rafx-gles2")]
349            RafxBuffer::Gles2(_) => None,
350            #[cfg(feature = "rafx-gles3")]
351            RafxBuffer::Gles3(_) => None,
352            #[cfg(any(
353                feature = "rafx-empty",
354                not(any(
355                    feature = "rafx-dx12",
356                    feature = "rafx-metal",
357                    feature = "rafx-vulkan",
358                    feature = "rafx-gles2",
359                    feature = "rafx-gles3"
360                ))
361            ))]
362            RafxBuffer::Empty(_) => None,
363        }
364    }
365
366    /// Get the underlying gl API object. This provides access to any internally created
367    /// metal objects.
368    #[cfg(feature = "rafx-gles2")]
369    pub fn gles2_buffer(&self) -> Option<&RafxBufferGles2> {
370        match self {
371            #[cfg(feature = "rafx-dx12")]
372            RafxBuffer::Dx12(_) => None,
373            #[cfg(feature = "rafx-vulkan")]
374            RafxBuffer::Vk(_) => None,
375            #[cfg(feature = "rafx-metal")]
376            RafxBuffer::Metal(_) => None,
377            #[cfg(feature = "rafx-gles2")]
378            RafxBuffer::Gles2(inner) => Some(inner),
379            #[cfg(feature = "rafx-gles3")]
380            RafxBuffer::Gles3(_) => None,
381            #[cfg(any(
382                feature = "rafx-empty",
383                not(any(
384                    feature = "rafx-dx12",
385                    feature = "rafx-metal",
386                    feature = "rafx-vulkan",
387                    feature = "rafx-gles2",
388                    feature = "rafx-gles3"
389                ))
390            ))]
391            RafxBuffer::Empty(_) => None,
392        }
393    }
394
395    /// Get the underlying gl API object. This provides access to any internally created
396    /// metal objects.
397    #[cfg(feature = "rafx-gles3")]
398    pub fn gles3_buffer(&self) -> Option<&RafxBufferGles3> {
399        match self {
400            #[cfg(feature = "rafx-dx12")]
401            RafxBuffer::Dx12(_) => None,
402            #[cfg(feature = "rafx-vulkan")]
403            RafxBuffer::Vk(_) => None,
404            #[cfg(feature = "rafx-metal")]
405            RafxBuffer::Metal(_) => None,
406            #[cfg(feature = "rafx-gles2")]
407            RafxBuffer::Gles2(_) => None,
408            #[cfg(feature = "rafx-gles3")]
409            RafxBuffer::Gles3(inner) => Some(inner),
410            #[cfg(any(
411                feature = "rafx-empty",
412                not(any(
413                    feature = "rafx-dx12",
414                    feature = "rafx-metal",
415                    feature = "rafx-vulkan",
416                    feature = "rafx-gles2",
417                    feature = "rafx-gles3"
418                ))
419            ))]
420            RafxBuffer::Empty(_) => None,
421        }
422    }
423
424    /// Get the underlying metal API object. This provides access to any internally created
425    /// metal objects.
426    #[cfg(any(
427        feature = "rafx-empty",
428        not(any(
429            feature = "rafx-dx12",
430            feature = "rafx-metal",
431            feature = "rafx-vulkan",
432            feature = "rafx-gles2",
433            feature = "rafx-gles3"
434        ))
435    ))]
436    pub fn empty_buffer(&self) -> Option<&RafxBufferEmpty> {
437        match self {
438            #[cfg(feature = "rafx-dx12")]
439            RafxBuffer::Dx12(_) => None,
440            #[cfg(feature = "rafx-vulkan")]
441            RafxBuffer::Vk(_) => None,
442            #[cfg(feature = "rafx-metal")]
443            RafxBuffer::Metal(_) => None,
444            #[cfg(feature = "rafx-gles2")]
445            RafxBuffer::Gles2(_) => None,
446            #[cfg(feature = "rafx-gles3")]
447            RafxBuffer::Gles3(_) => None,
448            #[cfg(any(
449                feature = "rafx-empty",
450                not(any(
451                    feature = "rafx-dx12",
452                    feature = "rafx-metal",
453                    feature = "rafx-vulkan",
454                    feature = "rafx-gles2",
455                    feature = "rafx-gles3"
456                ))
457            ))]
458            RafxBuffer::Empty(inner) => Some(inner),
459        }
460    }
461}