rendy_resource/
buffer.rs

1//! Buffer usage, creation-info and wrappers.
2
3pub use rendy_core::hal::buffer::*;
4
5use {
6    crate::{
7        core::{device_owned, Device, DeviceId},
8        memory::{Block, Heaps, MappedRange, MemoryBlock, MemoryUsage},
9        CreationError,
10    },
11    relevant::Relevant,
12    rendy_core::hal::{device::Device as _, Backend},
13};
14
15/// Buffer info.
16#[derive(Clone, Copy, Debug)]
17pub struct BufferInfo {
18    /// Buffer size.
19    pub size: u64,
20
21    /// Buffer usage flags.
22    pub usage: Usage,
23}
24
25/// Generic buffer resource wrapper.
26///
27/// # Parameters
28///
29/// `B` - raw image type.
30#[derive(Debug)]
31pub struct Buffer<B: Backend> {
32    device: DeviceId,
33    raw: B::Buffer,
34    block: MemoryBlock<B>,
35    info: BufferInfo,
36    relevant: Relevant,
37}
38
39device_owned!(Buffer<B>);
40/// Alias for the error to create a buffer.
41pub type BufferCreationError = CreationError<rendy_core::hal::buffer::CreationError>;
42
43impl<B> Buffer<B>
44where
45    B: Backend,
46{
47    /// Create buffer, allocate memory block for it and bind.
48    ///
49    /// # Safety
50    ///
51    /// In order to guarantee that `Heap::allocate` will return
52    /// memory range owned by this `Device`,
53    /// this `Heaps` instance must always be used with this `Device` instance.
54    ///
55    /// Otherwise usage of hal methods must be always valid.
56    pub unsafe fn create(
57        device: &Device<B>,
58        heaps: &mut Heaps<B>,
59        info: BufferInfo,
60        memory_usage: impl MemoryUsage,
61    ) -> Result<Self, BufferCreationError> {
62        log::trace!("{:#?}@{:#?}", info, memory_usage);
63        assert_ne!(info.size, 0);
64
65        let mut buf = device
66            .create_buffer(info.size, info.usage)
67            .map_err(CreationError::Create)?;
68        let reqs = device.get_buffer_requirements(&buf);
69        let block = heaps
70            .allocate(
71                device,
72                reqs.type_mask as u32,
73                memory_usage,
74                reqs.size,
75                reqs.alignment,
76            )
77            .map_err(CreationError::Allocate)?;
78
79        device
80            .bind_buffer_memory(block.memory(), block.range().start, &mut buf)
81            .map_err(CreationError::Bind)?;
82
83        Ok(Buffer {
84            device: device.id(),
85            raw: buf,
86            block,
87            info,
88            relevant: Relevant,
89        })
90    }
91
92    /// Dispose of buffer resource.
93    /// Deallocate memory block.
94    pub unsafe fn dispose(self, device: &Device<B>, heaps: &mut Heaps<B>) {
95        self.assert_device_owner(device);
96        device.destroy_buffer(self.raw);
97        heaps.free(device, self.block);
98        self.relevant.dispose();
99    }
100
101    /// Get reference to raw buffer resource
102    pub fn raw(&self) -> &B::Buffer {
103        &self.raw
104    }
105
106    /// Get mutable reference to raw buffer resource
107    pub unsafe fn raw_mut(&mut self) -> &mut B::Buffer {
108        &mut self.raw
109    }
110
111    /// Get reference to memory block occupied by buffer.
112    pub fn block(&self) -> &MemoryBlock<B> {
113        &self.block
114    }
115
116    /// Get mutable reference to memory block occupied by buffer.
117    pub unsafe fn block_mut(&mut self) -> &mut MemoryBlock<B> {
118        &mut self.block
119    }
120
121    /// Get buffer info.
122    pub fn info(&self) -> &BufferInfo {
123        &self.info
124    }
125
126    /// Check if this buffer could is bound to CPU visible memory and therefore mappable.
127    /// If this function returns `false` `map` will always return `InvalidAccess`.
128    ///
129    /// [`map`]: #method.map
130    /// [`InvalidAccess`]: https://docs.rs/gfx-hal/0.1/rendy_core::hal/mapping/enum.Error.html#InvalidAccess
131    pub fn visible(&self) -> bool {
132        self.block
133            .properties()
134            .contains(rendy_core::hal::memory::Properties::CPU_VISIBLE)
135    }
136
137    /// Map range of the buffer to the CPU accessible memory.
138    pub fn map<'a>(
139        &'a mut self,
140        device: &Device<B>,
141        range: std::ops::Range<u64>,
142    ) -> Result<MappedRange<'a, B>, rendy_core::hal::device::MapError> {
143        self.block.map(device, range)
144    }
145
146    /// Get buffer info.
147    pub fn size(&self) -> u64 {
148        self.info().size
149    }
150}