#[repr(C)]pub struct Subbuffer<T: ?Sized> { /* private fields */ }
Expand description
A subpart of a buffer.
This type doesn’t correspond to any Vulkan object, it exists for API convenience. Most Vulkan functions that work with buffers take the buffer as argument as well as an offset and size within the buffer, which we can represent with a single subbuffer instead.
Subbuffer
also has a type parameter, which is a hint for how the data is going to be
interpreted by the host or device (or both). This is useful so that we can allocate
(sub)buffers that are correctly aligned and have the correct size for their content, and for
type-safety. For example, when reading/writing a subbuffer from the host, you can use
Subbuffer::read
/Subbuffer::write
without worrying about the alignment and size being
correct and about converting your data from/to raw bytes.
There are two ways to get a Subbuffer
:
- By using the functions on
Buffer
, which create a new buffer and memory allocation each time, and give you aSubbuffer
that has an entireBuffer
dedicated to it. - By using the
SubbufferAllocator
, which createsSubbuffer
s by suballocating existingBuffer
s such that theBuffer
s can keep being reused.
Alternatively, you can also create a Buffer
manually and convert it to a Subbuffer<[u8]>
.
Implementations§
source§impl<T: ?Sized> Subbuffer<T>
impl<T: ?Sized> Subbuffer<T>
sourcepub fn offset(&self) -> DeviceSize
pub fn offset(&self) -> DeviceSize
Returns the offset of the subbuffer, in bytes, relative to the buffer.
sourcepub fn size(&self) -> DeviceSize
pub fn size(&self) -> DeviceSize
Returns the size of the subbuffer in bytes.
sourcepub fn mapped_slice(&self) -> Result<NonNull<[u8]>, HostAccessError>
pub fn mapped_slice(&self) -> Result<NonNull<[u8]>, HostAccessError>
Returns the mapped pointer to the range of memory of self
.
The subbuffer must fall within the range of the memory mapping given to
DeviceMemory::map
.
See MappingState::slice
for the safety invariants of the returned pointer.
sourcepub fn device_address(
&self
) -> Result<NonNullDeviceAddress, Box<ValidationError>>
pub fn device_address( &self ) -> Result<NonNullDeviceAddress, Box<ValidationError>>
Returns the device address for this subbuffer.
sourcepub fn into_bytes(self) -> Subbuffer<[u8]>
pub fn into_bytes(self) -> Subbuffer<[u8]>
Casts the subbuffer to a slice of raw bytes.
sourcepub fn as_bytes(&self) -> &Subbuffer<[u8]>
pub fn as_bytes(&self) -> &Subbuffer<[u8]>
Same as into_bytes
, except it works with a reference to the subbuffer.
source§impl<T> Subbuffer<T>where
T: BufferContents + ?Sized,
impl<T> Subbuffer<T>where T: BufferContents + ?Sized,
sourcepub fn reinterpret<U>(self) -> Subbuffer<U>where
U: BufferContents + ?Sized,
pub fn reinterpret<U>(self) -> Subbuffer<U>where U: BufferContents + ?Sized,
Changes the T
generic parameter of the subbuffer to the desired type.
Panics
- Panics if the memory offset of the subbuffer is not a multiple of the alignment of
U
. - If
U
is sized, then panics if the subbuffer size doesn’t match the size ofU
exactly. - If
U
is unsized, then panics if- the subbuffer size isn’t greater than the size of the head (sized part) of
U
, - the subbuffer would have slop when reinterpreted as
U
, meaning that the subbuffer size minus the the size of the head ofU
isn’t divisible by the element size ofU
, or - the subbuffer size isn’t a multiple of the alignment of
U
.
- the subbuffer size isn’t greater than the size of the head (sized part) of
sourcepub fn reinterpret_ref<U>(&self) -> &Subbuffer<U>where
U: BufferContents + ?Sized,
pub fn reinterpret_ref<U>(&self) -> &Subbuffer<U>where U: BufferContents + ?Sized,
Same as reinterpret
, except it works with a reference to the subbuffer.
sourcepub fn read(&self) -> Result<BufferReadGuard<'_, T>, HostAccessError>
pub fn read(&self) -> Result<BufferReadGuard<'_, T>, HostAccessError>
Locks the subbuffer in order to read its content from the host.
If the subbuffer is currently used in exclusive mode by the device, this function will
return an error. Similarly if you called write
on the buffer and haven’t dropped the
lock, this function will return an error as well.
After this function successfully locks the subbuffer, any attempt to submit a command buffer that uses it in exclusive mode will fail. You can still submit this subbuffer for non-exclusive accesses (ie. reads).
If the memory backing the buffer is not host-coherent, then this function will lock a
range that is potentially larger than the subbuffer, because the range given to
invalidate_range
must be aligned to the non_coherent_atom_size
. This means that for
example if your Vulkan implementation reports an atom size of 64, and you tried to put 2
subbuffers of size 32 in the same buffer, one at offset 0 and one at offset 32, while the
buffer is backed by non-coherent memory, then invalidating one subbuffer would also
invalidate the other subbuffer. This can lead to data races and is therefore not allowed.
What you should do in that case is ensure that each subbuffer is aligned to the
non-coherent atom size, so in this case one would be at offset 0 and the other at offset
64. SubbufferAllocator
does this automatically.
sourcepub fn write(&self) -> Result<BufferWriteGuard<'_, T>, HostAccessError>
pub fn write(&self) -> Result<BufferWriteGuard<'_, T>, HostAccessError>
Locks the subbuffer in order to write its content from the host.
If the subbuffer is currently in use by the device, this function will return an error.
Similarly if you called read
on the subbuffer and haven’t dropped the lock, this
function will return an error as well.
After this function successfully locks the buffer, any attempt to submit a command buffer
that uses it and any attempt to call read
will return an error.
If the memory backing the buffer is not host-coherent, then this function will lock a
range that is potentially larger than the subbuffer, because the range given to
flush_range
must be aligned to the non_coherent_atom_size
. This means that for
example if your Vulkan implementation reports an atom size of 64, and you tried to put 2
subbuffers of size 32 in the same buffer, one at offset 0 and one at offset 32, while the
buffer is backed by non-coherent memory, then flushing one subbuffer would also flush the
other subbuffer. This can lead to data races and is therefore not allowed. What you should
do in that case is ensure that each subbuffer is aligned to the non-coherent atom size, so
in this case one would be at offset 0 and the other at offset 64. SubbufferAllocator
does this automatically.
source§impl<T> Subbuffer<T>
impl<T> Subbuffer<T>
sourcepub fn into_slice(self) -> Subbuffer<[T]>
pub fn into_slice(self) -> Subbuffer<[T]>
Converts the subbuffer to a slice of one element.
sourcepub fn as_slice(&self) -> &Subbuffer<[T]>
pub fn as_slice(&self) -> &Subbuffer<[T]>
Same as into_slice
, except it works with a reference to the subbuffer.
source§impl<T> Subbuffer<[T]>
impl<T> Subbuffer<[T]>
sourcepub fn len(&self) -> DeviceSize
pub fn len(&self) -> DeviceSize
Returns the number of elements in the slice.
sourcepub fn index(self, index: DeviceSize) -> Subbuffer<T>
pub fn index(self, index: DeviceSize) -> Subbuffer<T>
sourcepub fn slice(self, range: impl RangeBounds<DeviceSize>) -> Subbuffer<[T]>
pub fn slice(self, range: impl RangeBounds<DeviceSize>) -> Subbuffer<[T]>
Reduces the subbuffer to just a range of the slice.
Panics
- Panics if
range
is out of bounds. - Panics if
range
is empty.
source§impl Subbuffer<[u8]>
impl Subbuffer<[u8]>
sourcepub fn new(buffer: Arc<Buffer>) -> Self
pub fn new(buffer: Arc<Buffer>) -> Self
Creates a new Subbuffer<[u8]>
spanning the whole buffer.
sourcepub fn cast_aligned<T>(self) -> Subbuffer<[T]>where
T: BufferContents,
pub fn cast_aligned<T>(self) -> Subbuffer<[T]>where T: BufferContents,
Casts the slice to a different element type while ensuring correct alignment for the type.
The offset of the subbuffer is rounded up to the alignment of T
and the size abjusted for
the padding, then the size is rounded down to the nearest multiple of T
’s size.
Panics
- Panics if the aligned offset would be out of bounds.
sourcepub fn align_to(self, layout: DeviceLayout) -> Subbuffer<[u8]>
pub fn align_to(self, layout: DeviceLayout) -> Subbuffer<[u8]>
Aligns the subbuffer to the given layout
by rounding the offset up to
layout.alignment()
and adjusting the size for the padding, and then rounding the size
down to the nearest multiple of layout.size()
.
Panics
- Panics if the aligned offset would be out of bounds.
- Panics if
layout.alignment()
exceeds64
.