Skip to main content

vulkano/buffer/
mod.rs

1//! Location in memory that contains data.
2//!
3//! A Vulkan buffer is very similar to a buffer that you would use in programming languages in
4//! general, in the sense that it is a location in memory that contains data. The difference
5//! between a Vulkan buffer and a regular buffer is that the content of a Vulkan buffer is
6//! accessible from the GPU.
7//!
8//! Vulkano does not perform any specific marshalling of buffer data. The representation of the
9//! buffer in memory is identical between the CPU and GPU. Because the Rust compiler is allowed to
10//! reorder struct fields at will by default when using `#[repr(Rust)]`, it is advised to mark each
11//! struct requiring input assembly as `#[repr(C)]`. This forces Rust to follow the standard C
12//! procedure. Each element is laid out in memory in the order of declaration and aligned to a
13//! multiple of their alignment.
14//!
15//! # Multiple levels of abstraction
16//!
17//! - The low-level implementation of a buffer is [`RawBuffer`], which corresponds directly to a
18//!   `VkBuffer`, and as such doesn't hold onto any memory.
19//! - [`Buffer`] is a `RawBuffer` with memory bound to it, and with state tracking.
20//! - [`Subbuffer`] is what you will use most of the time, as it is what all the APIs expect. It is
21//!   a reference to a portion of a `Buffer`. `Subbuffer` also has a type parameter, which is a
22//!   hint for how the data in the portion of the buffer is going to be interpreted.
23//!
24//! # `Subbuffer` allocation
25//!
26//! There are two ways to get a `Subbuffer`:
27//!
28//! - By using the functions on `Buffer`, which create a new buffer and memory allocation each
29//!   time, and give you a `Subbuffer` that has an entire `Buffer` dedicated to it.
30//! - By using the [`SubbufferAllocator`], which creates `Subbuffer`s by suballocating existing
31//!   `Buffer`s such that the `Buffer`s can keep being reused.
32//!
33//! Which of these you should choose depends on the use case. For example, if you need to upload
34//! data to the device each frame, then you should use `SubbufferAllocator`. Same goes for if you
35//! need to download data very frequently, or if you need to allocate a lot of intermediary buffers
36//! that are only accessed by the device. On the other hand, if you need to upload some data just
37//! once, or you can keep reusing the same buffer (because its size is unchanging) it's best to
38//! use a dedicated `Buffer` for that.
39//!
40//! # Buffer usage
41//!
42//! When you create a buffer, you have to specify its *usage*. In other words, you have to
43//! specify the way it is going to be used. Trying to use a buffer in a way that wasn't specified
44//! when you created it will result in a runtime error.
45//!
46//! You can use buffers for the following purposes:
47//!
48//! - Can contain arbitrary data that can be transferred from/to other buffers and images.
49//! - Can be read and modified from a shader.
50//! - Can be used as a source of vertices and indices.
51//! - Can be used as a source of list of models for draw indirect commands.
52//!
53//! Accessing a buffer from a shader can be done in the following ways:
54//!
55//! - As a uniform buffer. Uniform buffers are read-only.
56//! - As a storage buffer. Storage buffers can be read and written.
57//! - As a uniform texel buffer. Contrary to a uniform buffer, the data is interpreted by the GPU
58//!   and can be for example normalized.
59//! - As a storage texel buffer. Additionally, some data formats can be modified with atomic
60//!   operations.
61//!
62//! Using uniform/storage texel buffers requires creating a *buffer view*. See [the `view` module]
63//! for how to create a buffer view.
64//!
65//! See also [the `shader` module documentation] for information about how buffer contents need to
66//! be laid out in accordance with the shader interface.
67//!
68//! [`SubbufferAllocator`]: allocator::SubbufferAllocator
69//! [the `view` module]: view
70//! [the `shader` module documentation]: crate::shader
71
72pub use self::{subbuffer::*, sys::*, usage::*};
73use crate::{
74    device::{physical::PhysicalDevice, Device, DeviceOwned},
75    macros::{vulkan_bitflags, vulkan_enum},
76    memory::{
77        allocator::{
78            AllocationCreateInfo, AllocationType, DeviceLayout, MemoryAllocator,
79            MemoryAllocatorError,
80        },
81        DedicatedAllocation, ExternalMemoryHandleType, ExternalMemoryHandleTypes,
82        ExternalMemoryProperties, MemoryRequirements, ResourceMemory,
83    },
84    range_map::RangeMap,
85    sync::{future::AccessError, AccessConflict, CurrentAccess, Sharing},
86    DeviceSize, NonNullDeviceAddress, Requires, RequiresAllOf, RequiresOneOf, Validated,
87    ValidationError, Version, VulkanError, VulkanObject,
88};
89use parking_lot::{Mutex, MutexGuard};
90use smallvec::SmallVec;
91use std::{
92    error::Error,
93    fmt::{Display, Formatter},
94    hash::{Hash, Hasher},
95    marker::PhantomData,
96    ops::Range,
97    sync::Arc,
98};
99
100pub mod allocator;
101pub mod subbuffer;
102pub mod sys;
103mod usage;
104pub mod view;
105
106/// A storage for raw bytes.
107///
108/// Unlike [`RawBuffer`], a `Buffer` has memory backing it, and can be used normally.
109///
110/// See [the module-level documentation] for more information about buffers.
111///
112/// # Examples
113///
114/// Sometimes, you need a buffer that is rarely accessed by the host. To get the best performance
115/// in this case, one should use a buffer in device-local memory, that is inaccessible from the
116/// host. As such, to initialize or otherwise access such a buffer, we need a *staging buffer*.
117///
118/// The following example outlines the general strategy one may take when initializing a
119/// device-local buffer.
120///
121/// ```
122/// use vulkano::{
123///     buffer::{BufferUsage, Buffer, BufferCreateInfo},
124///     command_buffer::{
125///         AutoCommandBufferBuilder, CommandBufferUsage, CopyBufferInfo,
126///         PrimaryCommandBufferAbstract,
127///     },
128///     memory::allocator::{AllocationCreateInfo, MemoryTypeFilter},
129///     sync::GpuFuture,
130///     DeviceSize,
131/// };
132///
133/// # let device: std::sync::Arc<vulkano::device::Device> = return;
134/// # let queue: std::sync::Arc<vulkano::device::Queue> = return;
135/// # let memory_allocator: std::sync::Arc<vulkano::memory::allocator::StandardMemoryAllocator> = return;
136/// # let command_buffer_allocator: std::sync::Arc<vulkano::command_buffer::allocator::StandardCommandBufferAllocator> = return;
137/// #
138/// // Simple iterator to construct test data.
139/// let data = (0..10_000).map(|i| i as f32);
140///
141/// // Create a host-accessible buffer initialized with the data.
142/// let temporary_accessible_buffer = Buffer::from_iter(
143///     memory_allocator.clone(),
144///     BufferCreateInfo {
145///         // Specify that this buffer will be used as a transfer source.
146///         usage: BufferUsage::TRANSFER_SRC,
147///         ..Default::default()
148///     },
149///     AllocationCreateInfo {
150///         // Specify use for upload to the device.
151///         memory_type_filter: MemoryTypeFilter::PREFER_HOST
152///             | MemoryTypeFilter::HOST_SEQUENTIAL_WRITE,
153///         ..Default::default()
154///     },
155///     data,
156/// )
157/// .unwrap();
158///
159/// // Create a buffer in device-local memory with enough space for a slice of `10_000` floats.
160/// let device_local_buffer = Buffer::new_slice::<f32>(
161///     memory_allocator.clone(),
162///     BufferCreateInfo {
163///         // Specify use as a storage buffer and transfer destination.
164///         usage: BufferUsage::STORAGE_BUFFER | BufferUsage::TRANSFER_DST,
165///         ..Default::default()
166///     },
167///     AllocationCreateInfo {
168///         // Specify use by the device only.
169///         memory_type_filter: MemoryTypeFilter::PREFER_DEVICE,
170///         ..Default::default()
171///     },
172///     10_000 as DeviceSize,
173/// )
174/// .unwrap();
175///
176/// // Create a one-time command to copy between the buffers.
177/// let mut cbb = AutoCommandBufferBuilder::primary(
178///     command_buffer_allocator.clone(),
179///     queue.queue_family_index(),
180///     CommandBufferUsage::OneTimeSubmit,
181/// )
182/// .unwrap();
183/// cbb.copy_buffer(CopyBufferInfo::buffers(
184///     temporary_accessible_buffer,
185///     device_local_buffer.clone(),
186/// ))
187/// .unwrap();
188/// let cb = cbb.build().unwrap();
189///
190/// // Execute the copy command and wait for completion before proceeding.
191/// cb.execute(queue.clone())
192///     .unwrap()
193///     .then_signal_fence_and_flush()
194///     .unwrap()
195///     .wait(None /* timeout */)
196///     .unwrap()
197/// ```
198///
199/// [the module-level documentation]: self
200#[derive(Debug)]
201pub struct Buffer {
202    inner: RawBuffer,
203    memory: BufferMemory,
204    state: Mutex<BufferState>,
205}
206
207/// The type of backing memory that a buffer can have.
208#[derive(Debug)]
209#[non_exhaustive]
210pub enum BufferMemory {
211    /// The buffer is backed by normal memory, bound with [`bind_memory`].
212    ///
213    /// [`bind_memory`]: RawBuffer::bind_memory
214    Normal(ResourceMemory),
215
216    /// The buffer is backed by sparse memory, bound with [`bind_sparse`].
217    ///
218    /// [`bind_sparse`]: crate::device::QueueGuard::bind_sparse
219    Sparse,
220
221    /// The buffer is backed by memory not managed by vulkano.
222    External,
223}
224
225impl Buffer {
226    /// Creates a new `Buffer` and writes `data` in it. Returns a [`Subbuffer`] spanning the whole
227    /// buffer.
228    ///
229    /// > **Note**: This only works with memory types that are host-visible. If you want to upload
230    /// > data to a buffer allocated in device-local memory, you will need to create a staging
231    /// > buffer and copy the contents over.
232    ///
233    /// # Panics
234    ///
235    /// - Panics if `create_info.size` is not zero.
236    /// - Panics if the chosen memory type is not host-visible.
237    pub fn from_data<T>(
238        allocator: Arc<dyn MemoryAllocator>,
239        create_info: BufferCreateInfo,
240        allocation_info: AllocationCreateInfo,
241        data: T,
242    ) -> Result<Subbuffer<T>, Validated<AllocateBufferError>>
243    where
244        T: BufferContents,
245    {
246        let buffer = Buffer::new_sized(allocator, create_info, allocation_info)?;
247
248        {
249            let mut write_guard = buffer.write().unwrap();
250            *write_guard = data;
251        }
252
253        Ok(buffer)
254    }
255
256    /// Creates a new `Buffer` and writes all elements of `iter` in it. Returns a [`Subbuffer`]
257    /// spanning the whole buffer.
258    ///
259    /// > **Note**: This only works with memory types that are host-visible. If you want to upload
260    /// > data to a buffer allocated in device-local memory, you will need to create a staging
261    /// > buffer and copy the contents over.
262    ///
263    /// # Panics
264    ///
265    /// - Panics if `create_info.size` is not zero.
266    /// - Panics if the chosen memory type is not host-visible.
267    /// - Panics if `iter` is empty.
268    pub fn from_iter<T, I>(
269        allocator: Arc<dyn MemoryAllocator>,
270        create_info: BufferCreateInfo,
271        allocation_info: AllocationCreateInfo,
272        iter: I,
273    ) -> Result<Subbuffer<[T]>, Validated<AllocateBufferError>>
274    where
275        T: BufferContents,
276        I: IntoIterator<Item = T>,
277        I::IntoIter: ExactSizeIterator,
278    {
279        let iter = iter.into_iter();
280        let buffer = Buffer::new_slice(
281            allocator,
282            create_info,
283            allocation_info,
284            iter.len().try_into().unwrap(),
285        )?;
286
287        {
288            let mut write_guard = buffer.write().unwrap();
289
290            for (o, i) in write_guard.iter_mut().zip(iter) {
291                *o = i;
292            }
293        }
294
295        Ok(buffer)
296    }
297
298    /// Creates a new uninitialized `Buffer` for sized data. Returns a [`Subbuffer`] spanning the
299    /// whole buffer.
300    ///
301    /// # Panics
302    ///
303    /// - Panics if `create_info.size` is not zero.
304    pub fn new_sized<T>(
305        allocator: Arc<dyn MemoryAllocator>,
306        create_info: BufferCreateInfo,
307        allocation_info: AllocationCreateInfo,
308    ) -> Result<Subbuffer<T>, Validated<AllocateBufferError>>
309    where
310        T: BufferContents,
311    {
312        let layout = T::LAYOUT.unwrap_sized();
313        let buffer = Subbuffer::new(Buffer::new(
314            allocator,
315            create_info,
316            allocation_info,
317            layout,
318        )?);
319
320        Ok(unsafe { buffer.reinterpret_unchecked() })
321    }
322
323    /// Creates a new uninitialized `Buffer` for a slice. Returns a [`Subbuffer`] spanning the
324    /// whole buffer.
325    ///
326    /// # Panics
327    ///
328    /// - Panics if `create_info.size` is not zero.
329    /// - Panics if `len` is zero.
330    pub fn new_slice<T>(
331        allocator: Arc<dyn MemoryAllocator>,
332        create_info: BufferCreateInfo,
333        allocation_info: AllocationCreateInfo,
334        len: DeviceSize,
335    ) -> Result<Subbuffer<[T]>, Validated<AllocateBufferError>>
336    where
337        T: BufferContents,
338    {
339        Buffer::new_unsized(allocator, create_info, allocation_info, len)
340    }
341
342    /// Creates a new uninitialized `Buffer` for unsized data. Returns a [`Subbuffer`] spanning the
343    /// whole buffer.
344    ///
345    /// # Panics
346    ///
347    /// - Panics if `create_info.size` is not zero.
348    /// - Panics if `len` is zero.
349    pub fn new_unsized<T>(
350        allocator: Arc<dyn MemoryAllocator>,
351        create_info: BufferCreateInfo,
352        allocation_info: AllocationCreateInfo,
353        len: DeviceSize,
354    ) -> Result<Subbuffer<T>, Validated<AllocateBufferError>>
355    where
356        T: BufferContents + ?Sized,
357    {
358        let layout = T::LAYOUT.layout_for_len(len).unwrap();
359        let buffer = Subbuffer::new(Buffer::new(
360            allocator,
361            create_info,
362            allocation_info,
363            layout,
364        )?);
365
366        Ok(unsafe { buffer.reinterpret_unchecked() })
367    }
368
369    /// Creates a new uninitialized `Buffer` with the given `layout`.
370    ///
371    /// # Panics
372    ///
373    /// - Panics if `create_info.size` is not zero.
374    pub fn new(
375        allocator: Arc<dyn MemoryAllocator>,
376        mut create_info: BufferCreateInfo,
377        allocation_info: AllocationCreateInfo,
378        layout: DeviceLayout,
379    ) -> Result<Arc<Self>, Validated<AllocateBufferError>> {
380        assert!(!create_info
381            .flags
382            .contains(BufferCreateFlags::SPARSE_BINDING));
383
384        assert_eq!(
385            create_info.size, 0,
386            "`Buffer::new*` functions set the `create_info.size` field themselves, you should not \
387             set it yourself"
388        );
389
390        create_info.size = layout.size();
391
392        let raw_buffer =
393            RawBuffer::new(allocator.device().clone(), create_info).map_err(|err| match err {
394                Validated::Error(err) => Validated::Error(AllocateBufferError::CreateBuffer(err)),
395                Validated::ValidationError(err) => err.into(),
396            })?;
397        let mut requirements = *raw_buffer.memory_requirements();
398        requirements.layout = requirements.layout.align_to(layout.alignment()).unwrap();
399
400        let allocation = allocator
401            .allocate(
402                requirements,
403                AllocationType::Linear,
404                allocation_info,
405                Some(DedicatedAllocation::Buffer(&raw_buffer)),
406            )
407            .map_err(AllocateBufferError::AllocateMemory)?;
408        let allocation = unsafe { ResourceMemory::from_allocation(allocator, allocation) };
409
410        let buffer = raw_buffer.bind_memory(allocation).map_err(|(err, _, _)| {
411            err.map(AllocateBufferError::BindMemory)
412                .map_validation(|err| err.add_context("RawBuffer::bind_memory"))
413        })?;
414
415        Ok(Arc::new(buffer))
416    }
417
418    fn from_raw(inner: RawBuffer, memory: BufferMemory) -> Self {
419        let state = Mutex::new(BufferState::new(inner.size()));
420
421        Buffer {
422            inner,
423            memory,
424            state,
425        }
426    }
427
428    /// Returns the type of memory that is backing this buffer.
429    #[inline]
430    pub fn memory(&self) -> &BufferMemory {
431        &self.memory
432    }
433
434    /// Returns the memory requirements for this buffer.
435    #[inline]
436    pub fn memory_requirements(&self) -> &MemoryRequirements {
437        self.inner.memory_requirements()
438    }
439
440    /// Returns the flags the buffer was created with.
441    #[inline]
442    pub fn flags(&self) -> BufferCreateFlags {
443        self.inner.flags()
444    }
445
446    /// Returns the size of the buffer in bytes.
447    #[inline]
448    pub fn size(&self) -> DeviceSize {
449        self.inner.size()
450    }
451
452    /// Returns the usage the buffer was created with.
453    #[inline]
454    pub fn usage(&self) -> BufferUsage {
455        self.inner.usage()
456    }
457
458    /// Returns the sharing the buffer was created with.
459    #[inline]
460    pub fn sharing(&self) -> &Sharing<SmallVec<[u32; 4]>> {
461        self.inner.sharing()
462    }
463
464    /// Returns the external memory handle types that are supported with this buffer.
465    #[inline]
466    pub fn external_memory_handle_types(&self) -> ExternalMemoryHandleTypes {
467        self.inner.external_memory_handle_types()
468    }
469
470    /// Returns the device address for this buffer.
471    // TODO: Caching?
472    pub fn device_address(&self) -> Result<NonNullDeviceAddress, Box<ValidationError>> {
473        self.validate_device_address()?;
474
475        Ok(unsafe { self.device_address_unchecked() })
476    }
477
478    fn validate_device_address(&self) -> Result<(), Box<ValidationError>> {
479        let device = self.device();
480
481        if !device.enabled_features().buffer_device_address {
482            return Err(Box::new(ValidationError {
483                requires_one_of: RequiresOneOf(&[RequiresAllOf(&[Requires::DeviceFeature(
484                    "buffer_device_address",
485                )])]),
486                vuids: &["VUID-vkGetBufferDeviceAddress-bufferDeviceAddress-03324"],
487                ..Default::default()
488            }));
489        }
490
491        if !self.usage().intersects(BufferUsage::SHADER_DEVICE_ADDRESS) {
492            return Err(Box::new(ValidationError {
493                context: "self.usage()".into(),
494                problem: "does not contain `BufferUsage::SHADER_DEVICE_ADDRESS`".into(),
495                vuids: &["VUID-VkBufferDeviceAddressInfo-buffer-02601"],
496                ..Default::default()
497            }));
498        }
499
500        Ok(())
501    }
502
503    #[cfg_attr(not(feature = "document_unchecked"), doc(hidden))]
504    pub unsafe fn device_address_unchecked(&self) -> NonNullDeviceAddress {
505        let device = self.device();
506
507        let info_vk = ash::vk::BufferDeviceAddressInfo::default().buffer(self.handle());
508
509        let ptr = {
510            let fns = device.fns();
511            let func = if device.api_version() >= Version::V1_2 {
512                fns.v1_2.get_buffer_device_address
513            } else if device.enabled_extensions().khr_buffer_device_address {
514                fns.khr_buffer_device_address.get_buffer_device_address_khr
515            } else {
516                fns.ext_buffer_device_address.get_buffer_device_address_ext
517            };
518            unsafe { func(device.handle(), &info_vk) }
519        };
520
521        NonNullDeviceAddress::new(ptr).unwrap()
522    }
523
524    pub(crate) fn state(&self) -> MutexGuard<'_, BufferState> {
525        self.state.lock()
526    }
527}
528
529unsafe impl VulkanObject for Buffer {
530    type Handle = ash::vk::Buffer;
531
532    #[inline]
533    fn handle(&self) -> Self::Handle {
534        self.inner.handle()
535    }
536}
537
538unsafe impl DeviceOwned for Buffer {
539    #[inline]
540    fn device(&self) -> &Arc<Device> {
541        self.inner.device()
542    }
543}
544
545impl PartialEq for Buffer {
546    #[inline]
547    fn eq(&self, other: &Self) -> bool {
548        self.inner == other.inner
549    }
550}
551
552impl Eq for Buffer {}
553
554impl Hash for Buffer {
555    fn hash<H: Hasher>(&self, state: &mut H) {
556        self.inner.hash(state);
557    }
558}
559
560/// Error that can happen when allocating a new buffer.
561#[derive(Clone, Debug)]
562pub enum AllocateBufferError {
563    CreateBuffer(VulkanError),
564    AllocateMemory(MemoryAllocatorError),
565    BindMemory(VulkanError),
566}
567
568impl Error for AllocateBufferError {
569    fn source(&self) -> Option<&(dyn Error + 'static)> {
570        match self {
571            Self::CreateBuffer(err) => Some(err),
572            Self::AllocateMemory(err) => Some(err),
573            Self::BindMemory(err) => Some(err),
574        }
575    }
576}
577
578impl Display for AllocateBufferError {
579    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
580        match self {
581            Self::CreateBuffer(_) => write!(f, "creating the buffer failed"),
582            Self::AllocateMemory(_) => write!(f, "allocating memory for the buffer failed"),
583            Self::BindMemory(_) => write!(f, "binding memory to the buffer failed"),
584        }
585    }
586}
587
588impl From<AllocateBufferError> for Validated<AllocateBufferError> {
589    fn from(err: AllocateBufferError) -> Self {
590        Self::Error(err)
591    }
592}
593
594/// The current state of a buffer.
595#[derive(Debug)]
596pub(crate) struct BufferState {
597    ranges: RangeMap<DeviceSize, BufferRangeState>,
598}
599
600impl BufferState {
601    fn new(size: DeviceSize) -> Self {
602        BufferState {
603            ranges: [(
604                0..size,
605                BufferRangeState {
606                    current_access: CurrentAccess::Shared {
607                        cpu_reads: 0,
608                        gpu_reads: 0,
609                    },
610                },
611            )]
612            .into_iter()
613            .collect(),
614        }
615    }
616
617    pub(crate) fn check_cpu_read(&self, range: Range<DeviceSize>) -> Result<(), AccessConflict> {
618        for (_range, state) in self.ranges.range(&range) {
619            match &state.current_access {
620                CurrentAccess::CpuExclusive { .. } => return Err(AccessConflict::HostWrite),
621                CurrentAccess::GpuExclusive { .. } => return Err(AccessConflict::DeviceWrite),
622                CurrentAccess::Shared { .. } => (),
623            }
624        }
625
626        Ok(())
627    }
628
629    pub(crate) unsafe fn cpu_read_lock(&mut self, range: Range<DeviceSize>) {
630        self.ranges.split_at(&range.start);
631        self.ranges.split_at(&range.end);
632
633        for (_range, state) in self.ranges.range_mut(&range) {
634            match &mut state.current_access {
635                CurrentAccess::Shared { cpu_reads, .. } => {
636                    *cpu_reads += 1;
637                }
638                _ => unreachable!("Buffer is being written by the CPU or GPU"),
639            }
640        }
641    }
642
643    pub(crate) unsafe fn cpu_read_unlock(&mut self, range: Range<DeviceSize>) {
644        self.ranges.split_at(&range.start);
645        self.ranges.split_at(&range.end);
646
647        for (_range, state) in self.ranges.range_mut(&range) {
648            match &mut state.current_access {
649                CurrentAccess::Shared { cpu_reads, .. } => *cpu_reads -= 1,
650                _ => unreachable!("Buffer was not locked for CPU read"),
651            }
652        }
653    }
654
655    pub(crate) fn check_cpu_write(&self, range: Range<DeviceSize>) -> Result<(), AccessConflict> {
656        for (_range, state) in self.ranges.range(&range) {
657            match &state.current_access {
658                CurrentAccess::CpuExclusive => return Err(AccessConflict::HostWrite),
659                CurrentAccess::GpuExclusive { .. } => return Err(AccessConflict::DeviceWrite),
660                CurrentAccess::Shared {
661                    cpu_reads: 0,
662                    gpu_reads: 0,
663                } => (),
664                CurrentAccess::Shared { cpu_reads, .. } if *cpu_reads > 0 => {
665                    return Err(AccessConflict::HostRead);
666                }
667                CurrentAccess::Shared { .. } => return Err(AccessConflict::DeviceRead),
668            }
669        }
670
671        Ok(())
672    }
673
674    pub(crate) unsafe fn cpu_write_lock(&mut self, range: Range<DeviceSize>) {
675        self.ranges.split_at(&range.start);
676        self.ranges.split_at(&range.end);
677
678        for (_range, state) in self.ranges.range_mut(&range) {
679            state.current_access = CurrentAccess::CpuExclusive;
680        }
681    }
682
683    pub(crate) unsafe fn cpu_write_unlock(&mut self, range: Range<DeviceSize>) {
684        self.ranges.split_at(&range.start);
685        self.ranges.split_at(&range.end);
686
687        for (_range, state) in self.ranges.range_mut(&range) {
688            match &mut state.current_access {
689                CurrentAccess::CpuExclusive => {
690                    state.current_access = CurrentAccess::Shared {
691                        cpu_reads: 0,
692                        gpu_reads: 0,
693                    }
694                }
695                _ => unreachable!("Buffer was not locked for CPU write"),
696            }
697        }
698    }
699
700    pub(crate) fn check_gpu_read(&self, range: Range<DeviceSize>) -> Result<(), AccessError> {
701        for (_range, state) in self.ranges.range(&range) {
702            match &state.current_access {
703                CurrentAccess::Shared { .. } => (),
704                _ => return Err(AccessError::AlreadyInUse),
705            }
706        }
707
708        Ok(())
709    }
710
711    pub(crate) unsafe fn gpu_read_lock(&mut self, range: Range<DeviceSize>) {
712        self.ranges.split_at(&range.start);
713        self.ranges.split_at(&range.end);
714
715        for (_range, state) in self.ranges.range_mut(&range) {
716            match &mut state.current_access {
717                CurrentAccess::GpuExclusive { gpu_reads, .. }
718                | CurrentAccess::Shared { gpu_reads, .. } => *gpu_reads += 1,
719                _ => unreachable!("Buffer is being written by the CPU"),
720            }
721        }
722    }
723
724    pub(crate) unsafe fn gpu_read_unlock(&mut self, range: Range<DeviceSize>) {
725        self.ranges.split_at(&range.start);
726        self.ranges.split_at(&range.end);
727
728        for (_range, state) in self.ranges.range_mut(&range) {
729            match &mut state.current_access {
730                CurrentAccess::GpuExclusive { gpu_reads, .. } => *gpu_reads -= 1,
731                CurrentAccess::Shared { gpu_reads, .. } => *gpu_reads -= 1,
732                _ => unreachable!("Buffer was not locked for GPU read"),
733            }
734        }
735    }
736
737    pub(crate) fn check_gpu_write(&self, range: Range<DeviceSize>) -> Result<(), AccessError> {
738        for (_range, state) in self.ranges.range(&range) {
739            match &state.current_access {
740                CurrentAccess::Shared {
741                    cpu_reads: 0,
742                    gpu_reads: 0,
743                } => (),
744                _ => return Err(AccessError::AlreadyInUse),
745            }
746        }
747
748        Ok(())
749    }
750
751    pub(crate) unsafe fn gpu_write_lock(&mut self, range: Range<DeviceSize>) {
752        self.ranges.split_at(&range.start);
753        self.ranges.split_at(&range.end);
754
755        for (_range, state) in self.ranges.range_mut(&range) {
756            match &mut state.current_access {
757                CurrentAccess::GpuExclusive { gpu_writes, .. } => *gpu_writes += 1,
758                &mut CurrentAccess::Shared {
759                    cpu_reads: 0,
760                    gpu_reads,
761                } => {
762                    state.current_access = CurrentAccess::GpuExclusive {
763                        gpu_reads,
764                        gpu_writes: 1,
765                    }
766                }
767                _ => unreachable!("Buffer is being accessed by the CPU"),
768            }
769        }
770    }
771
772    pub(crate) unsafe fn gpu_write_unlock(&mut self, range: Range<DeviceSize>) {
773        self.ranges.split_at(&range.start);
774        self.ranges.split_at(&range.end);
775
776        for (_range, state) in self.ranges.range_mut(&range) {
777            match &mut state.current_access {
778                &mut CurrentAccess::GpuExclusive {
779                    gpu_reads,
780                    gpu_writes: 1,
781                } => {
782                    state.current_access = CurrentAccess::Shared {
783                        cpu_reads: 0,
784                        gpu_reads,
785                    }
786                }
787                CurrentAccess::GpuExclusive { gpu_writes, .. } => *gpu_writes -= 1,
788                _ => unreachable!("Buffer was not locked for GPU write"),
789            }
790        }
791    }
792}
793
794/// The current state of a specific range of bytes in a buffer.
795#[derive(Clone, Copy, Debug, PartialEq, Eq)]
796struct BufferRangeState {
797    current_access: CurrentAccess,
798}
799
800vulkan_bitflags! {
801    #[non_exhaustive]
802
803    /// Flags specifying additional properties of a buffer.
804    BufferCreateFlags = BufferCreateFlags(u32);
805
806    /// The buffer will be backed by sparse memory binding (through the [`bind_sparse`] queue
807    /// command) instead of regular binding (through [`bind_memory`]).
808    ///
809    /// The [`sparse_binding`] feature must be enabled on the device.
810    ///
811    /// [`bind_sparse`]: crate::device::queue::QueueGuard::bind_sparse
812    /// [`bind_memory`]: sys::RawBuffer::bind_memory
813    /// [`sparse_binding`]: crate::device::DeviceFeatures::sparse_binding
814    SPARSE_BINDING = SPARSE_BINDING,
815
816    /// The buffer can be used without being fully resident in memory at the time of use.
817    ///
818    /// This requires the [`BufferCreateFlags::SPARSE_BINDING`] flag as well.
819    ///
820    /// The [`sparse_residency_buffer`] feature must be enabled on the device.
821    ///
822    /// [`sparse_residency_buffer`]: crate::device::DeviceFeatures::sparse_residency_buffer
823    SPARSE_RESIDENCY = SPARSE_RESIDENCY,
824
825    /* TODO: enable
826    /// The buffer's memory can alias with another buffer or a different part of the same buffer.
827    ///
828    /// This requires the `sparse_binding` flag as well.
829    ///
830    /// The [`sparse_residency_aliased`] feature must be enabled on the device.
831    ///
832    /// [`sparse_residency_aliased`]: crate::device::DeviceFeatures::sparse_residency_aliased
833    SPARSE_ALIASED = SPARSE_ALIASED,*/
834
835    /* TODO: enable
836    /// The buffer is protected, and can only be used in combination with protected memory and other
837    /// protected objects.
838    ///
839    /// The device API version must be at least 1.1.
840    PROTECTED = PROTECTED
841    RequiresOneOf([
842        RequiresAllOf([APIVersion(V1_1)]),
843    ]),*/
844
845    /* TODO: enable
846    /// The buffer's device address can be saved and reused on a subsequent run.
847    ///
848    /// The device API version must be at least 1.2, or either the [`khr_buffer_device_address`] or
849    /// [`ext_buffer_device_address`] extension must be enabled on the device.
850    DEVICE_ADDRESS_CAPTURE_REPLAY = DEVICE_ADDRESS_CAPTURE_REPLAY {
851        api_version: V1_2,
852        device_extensions: [khr_buffer_device_address, ext_buffer_device_address],
853    },*/
854}
855
856/// The buffer configuration to query in [`PhysicalDevice::external_buffer_properties`].
857#[derive(Clone, Debug, PartialEq, Eq, Hash)]
858pub struct ExternalBufferInfo {
859    /// The flags that will be used.
860    pub flags: BufferCreateFlags,
861
862    /// The usage that the buffer will have.
863    pub usage: BufferUsage,
864
865    /// The external handle type that will be used with the buffer.
866    pub handle_type: ExternalMemoryHandleType,
867
868    pub _ne: crate::NonExhaustive,
869}
870
871impl ExternalBufferInfo {
872    /// Returns an `ExternalBufferInfo` with the specified `handle_type`.
873    #[inline]
874    pub fn handle_type(handle_type: ExternalMemoryHandleType) -> Self {
875        Self {
876            flags: BufferCreateFlags::empty(),
877            usage: BufferUsage::empty(),
878            handle_type,
879            _ne: crate::NonExhaustive(()),
880        }
881    }
882
883    pub(crate) fn validate(
884        &self,
885        physical_device: &PhysicalDevice,
886    ) -> Result<(), Box<ValidationError>> {
887        let &Self {
888            flags,
889            usage,
890            handle_type,
891            _ne: _,
892        } = self;
893
894        flags
895            .validate_physical_device(physical_device)
896            .map_err(|err| {
897                err.add_context("flags")
898                    .set_vuids(&["VUID-VkPhysicalDeviceExternalBufferInfo-flags-parameter"])
899            })?;
900
901        usage
902            .validate_physical_device(physical_device)
903            .map_err(|err| {
904                err.add_context("usage")
905                    .set_vuids(&["VUID-VkPhysicalDeviceExternalBufferInfo-usage-parameter"])
906            })?;
907
908        if usage.is_empty() {
909            return Err(Box::new(ValidationError {
910                context: "usage".into(),
911                problem: "is empty".into(),
912                vuids: &["VUID-VkPhysicalDeviceExternalBufferInfo-usage-requiredbitmask"],
913                ..Default::default()
914            }));
915        }
916
917        handle_type
918            .validate_physical_device(physical_device)
919            .map_err(|err| {
920                err.add_context("handle_type")
921                    .set_vuids(&["VUID-VkPhysicalDeviceExternalBufferInfo-handleType-parameter"])
922            })?;
923
924        Ok(())
925    }
926
927    pub(crate) fn to_vk(&self) -> ash::vk::PhysicalDeviceExternalBufferInfo<'static> {
928        let &Self {
929            flags,
930            usage,
931            handle_type,
932            _ne: _,
933        } = self;
934
935        ash::vk::PhysicalDeviceExternalBufferInfo::default()
936            .flags(flags.into())
937            .usage(usage.into())
938            .handle_type(handle_type.into())
939    }
940}
941
942/// The external memory properties supported for buffers with a given configuration.
943#[derive(Clone, Debug)]
944#[non_exhaustive]
945pub struct ExternalBufferProperties {
946    /// The properties for external memory.
947    pub external_memory_properties: ExternalMemoryProperties,
948}
949
950impl ExternalBufferProperties {
951    pub(crate) fn to_mut_vk() -> ash::vk::ExternalBufferProperties<'static> {
952        ash::vk::ExternalBufferProperties::default()
953    }
954
955    pub(crate) fn from_vk(val_vk: &ash::vk::ExternalBufferProperties<'_>) -> Self {
956        let &ash::vk::ExternalBufferProperties {
957            ref external_memory_properties,
958            ..
959        } = val_vk;
960
961        Self {
962            external_memory_properties: ExternalMemoryProperties::from_vk(
963                external_memory_properties,
964            ),
965        }
966    }
967}
968
969vulkan_enum! {
970    #[non_exhaustive]
971
972    /// An enumeration of all valid index types.
973    IndexType = IndexType(i32);
974
975    /// Indices are 8-bit unsigned integers.
976    U8 = UINT8_EXT
977    RequiresOneOf([
978        RequiresAllOf([DeviceExtension(ext_index_type_uint8)]),
979    ]),
980
981    /// Indices are 16-bit unsigned integers.
982    U16 = UINT16,
983
984    /// Indices are 32-bit unsigned integers.
985    U32 = UINT32,
986}
987
988impl IndexType {
989    /// Returns the size in bytes of indices of this type.
990    #[inline]
991    pub fn size(self) -> DeviceSize {
992        match self {
993            IndexType::U8 => 1,
994            IndexType::U16 => 2,
995            IndexType::U32 => 4,
996        }
997    }
998}
999
1000/// A buffer holding index values, which index into buffers holding vertex data.
1001#[derive(Clone, Debug)]
1002pub enum IndexBuffer {
1003    /// An index buffer containing unsigned 8-bit indices.
1004    ///
1005    /// The [`index_type_uint8`] feature must be enabled on the device.
1006    ///
1007    /// [`index_type_uint8`]: crate::device::DeviceFeatures::index_type_uint8
1008    U8(Subbuffer<[u8]>),
1009
1010    /// An index buffer containing unsigned 16-bit indices.
1011    U16(Subbuffer<[u16]>),
1012
1013    /// An index buffer containing unsigned 32-bit indices.
1014    U32(Subbuffer<[u32]>),
1015}
1016
1017impl IndexBuffer {
1018    /// Returns an `IndexType` value corresponding to the type of the buffer.
1019    #[inline]
1020    pub fn index_type(&self) -> IndexType {
1021        match self {
1022            Self::U8(_) => IndexType::U8,
1023            Self::U16(_) => IndexType::U16,
1024            Self::U32(_) => IndexType::U32,
1025        }
1026    }
1027
1028    /// Returns the buffer reinterpreted as a buffer of bytes.
1029    #[inline]
1030    pub fn as_bytes(&self) -> &Subbuffer<[u8]> {
1031        match self {
1032            IndexBuffer::U8(buffer) => buffer.as_bytes(),
1033            IndexBuffer::U16(buffer) => buffer.as_bytes(),
1034            IndexBuffer::U32(buffer) => buffer.as_bytes(),
1035        }
1036    }
1037
1038    /// Returns the number of elements in the buffer.
1039    #[inline]
1040    pub fn len(&self) -> DeviceSize {
1041        match self {
1042            IndexBuffer::U8(buffer) => buffer.len(),
1043            IndexBuffer::U16(buffer) => buffer.len(),
1044            IndexBuffer::U32(buffer) => buffer.len(),
1045        }
1046    }
1047}
1048
1049impl From<Subbuffer<[u8]>> for IndexBuffer {
1050    #[inline]
1051    fn from(value: Subbuffer<[u8]>) -> Self {
1052        Self::U8(value)
1053    }
1054}
1055
1056impl From<Subbuffer<[u16]>> for IndexBuffer {
1057    #[inline]
1058    fn from(value: Subbuffer<[u16]>) -> Self {
1059        Self::U16(value)
1060    }
1061}
1062
1063impl From<Subbuffer<[u32]>> for IndexBuffer {
1064    #[inline]
1065    fn from(value: Subbuffer<[u32]>) -> Self {
1066        Self::U32(value)
1067    }
1068}
1069
1070/// This is intended for use by the `BufferContents` derive macro only.
1071#[doc(hidden)]
1072pub struct AssertParamIsBufferContents<T: BufferContents + ?Sized>(PhantomData<T>);