aboutsummaryrefslogtreecommitdiff
path: root/src/command_buffer/pool/sys.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/command_buffer/pool/sys.rs')
-rw-r--r--src/command_buffer/pool/sys.rs421
1 files changed, 0 insertions, 421 deletions
diff --git a/src/command_buffer/pool/sys.rs b/src/command_buffer/pool/sys.rs
deleted file mode 100644
index 8432182..0000000
--- a/src/command_buffer/pool/sys.rs
+++ /dev/null
@@ -1,421 +0,0 @@
-// Copyright (c) 2016 The vulkano developers
-// Licensed under the Apache License, Version 2.0
-// <LICENSE-APACHE or
-// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
-// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
-// at your option. All files in the project carrying such
-// notice may not be copied, modified, or distributed except
-// according to those terms.
-
-use crate::check_errors;
-use crate::device::physical::QueueFamily;
-use crate::device::Device;
-use crate::device::DeviceOwned;
-use crate::Error;
-use crate::OomError;
-use crate::Version;
-use crate::VulkanObject;
-use smallvec::SmallVec;
-use std::error;
-use std::fmt;
-use std::marker::PhantomData;
-use std::mem::MaybeUninit;
-use std::ptr;
-use std::sync::Arc;
-use std::vec::IntoIter as VecIntoIter;
-
-/// Low-level implementation of a command pool.
-///
-/// A command pool is always tied to a specific queue family. Command buffers allocated from a pool
-/// can only be executed on the corresponding queue family.
-///
-/// This struct doesn't implement the `Sync` trait because Vulkan command pools are not thread
-/// safe. In other words, you can only use a pool from one thread at a time.
-#[derive(Debug)]
-pub struct UnsafeCommandPool {
- pool: ash::vk::CommandPool,
- device: Arc<Device>,
-
- // Index of the associated queue family in the physical device.
- queue_family_index: u32,
-
- // We don't want `UnsafeCommandPool` to implement Sync.
- // This marker unimplements both Send and Sync, but we reimplement Send manually right under.
- dummy_avoid_sync: PhantomData<*const u8>,
-}
-
-unsafe impl Send for UnsafeCommandPool {}
-
-impl UnsafeCommandPool {
- /// Creates a new pool.
- ///
- /// The command buffers created with this pool can only be executed on queues of the given
- /// family.
- ///
- /// Setting `transient` to true is a hint to the implementation that the command buffers will
- /// be short-lived.
- /// Setting `reset_cb` to true means that command buffers can be reset individually.
- ///
- /// # Panic
- ///
- /// - Panics if the queue family doesn't belong to the same physical device as `device`.
- ///
- pub fn new(
- device: Arc<Device>,
- queue_family: QueueFamily,
- transient: bool,
- reset_cb: bool,
- ) -> Result<UnsafeCommandPool, OomError> {
- assert_eq!(
- device.physical_device().internal_object(),
- queue_family.physical_device().internal_object(),
- "Device doesn't match physical device when creating a command pool"
- );
-
- let fns = device.fns();
-
- let flags = {
- let flag1 = if transient {
- ash::vk::CommandPoolCreateFlags::TRANSIENT
- } else {
- ash::vk::CommandPoolCreateFlags::empty()
- };
- let flag2 = if reset_cb {
- ash::vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER
- } else {
- ash::vk::CommandPoolCreateFlags::empty()
- };
- flag1 | flag2
- };
-
- let pool = unsafe {
- let infos = ash::vk::CommandPoolCreateInfo {
- flags: flags,
- queue_family_index: queue_family.id(),
- ..Default::default()
- };
-
- let mut output = MaybeUninit::uninit();
- check_errors(fns.v1_0.create_command_pool(
- device.internal_object(),
- &infos,
- ptr::null(),
- output.as_mut_ptr(),
- ))?;
- output.assume_init()
- };
-
- Ok(UnsafeCommandPool {
- pool: pool,
- device: device.clone(),
- queue_family_index: queue_family.id(),
- dummy_avoid_sync: PhantomData,
- })
- }
-
- /// Resets the pool, which resets all the command buffers that were allocated from it.
- ///
- /// If `release_resources` is true, it is a hint to the implementation that it should free all
- /// the memory internally allocated for this pool.
- ///
- /// # Safety
- ///
- /// The command buffers allocated from this pool jump to the initial state.
- ///
- pub unsafe fn reset(&self, release_resources: bool) -> Result<(), OomError> {
- let flags = if release_resources {
- ash::vk::CommandPoolResetFlags::RELEASE_RESOURCES
- } else {
- ash::vk::CommandPoolResetFlags::empty()
- };
-
- let fns = self.device.fns();
- check_errors(
- fns.v1_0
- .reset_command_pool(self.device.internal_object(), self.pool, flags),
- )?;
- Ok(())
- }
-
- /// Trims a command pool, which recycles unused internal memory from the command pool back to
- /// the system.
- ///
- /// Command buffers allocated from the pool are not affected by trimming.
- ///
- /// This function is supported only if the `VK_KHR_maintenance1` extension was enabled at
- /// device creation. Otherwise an error is returned.
- /// Since this operation is purely an optimization it is legitimate to call this function and
- /// simply ignore any possible error.
- pub fn trim(&self) -> Result<(), CommandPoolTrimError> {
- unsafe {
- if !(self.device.api_version() >= Version::V1_1
- || self.device.enabled_extensions().khr_maintenance1)
- {
- return Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled);
- }
-
- let fns = self.device.fns();
-
- if self.device.api_version() >= Version::V1_1 {
- fns.v1_1.trim_command_pool(
- self.device.internal_object(),
- self.pool,
- ash::vk::CommandPoolTrimFlags::empty(),
- );
- } else {
- fns.khr_maintenance1.trim_command_pool_khr(
- self.device.internal_object(),
- self.pool,
- ash::vk::CommandPoolTrimFlagsKHR::empty(),
- );
- }
-
- Ok(())
- }
- }
-
- /// Allocates `count` command buffers.
- ///
- /// If `secondary` is true, allocates secondary command buffers. Otherwise, allocates primary
- /// command buffers.
- pub fn alloc_command_buffers(
- &self,
- secondary: bool,
- count: u32,
- ) -> Result<UnsafeCommandPoolAllocIter, OomError> {
- if count == 0 {
- return Ok(UnsafeCommandPoolAllocIter {
- device: self.device.clone(),
- list: vec![].into_iter(),
- });
- }
-
- let infos = ash::vk::CommandBufferAllocateInfo {
- command_pool: self.pool,
- level: if secondary {
- ash::vk::CommandBufferLevel::SECONDARY
- } else {
- ash::vk::CommandBufferLevel::PRIMARY
- },
- command_buffer_count: count,
- ..Default::default()
- };
-
- unsafe {
- let fns = self.device.fns();
- let mut out = Vec::with_capacity(count as usize);
- check_errors(fns.v1_0.allocate_command_buffers(
- self.device.internal_object(),
- &infos,
- out.as_mut_ptr(),
- ))?;
-
- out.set_len(count as usize);
-
- Ok(UnsafeCommandPoolAllocIter {
- device: self.device.clone(),
- list: out.into_iter(),
- })
- }
- }
-
- /// Frees individual command buffers.
- ///
- /// # Safety
- ///
- /// The command buffers must have been allocated from this pool. They must not be in use.
- ///
- pub unsafe fn free_command_buffers<I>(&self, command_buffers: I)
- where
- I: Iterator<Item = UnsafeCommandPoolAlloc>,
- {
- let command_buffers: SmallVec<[_; 4]> =
- command_buffers.map(|cb| cb.command_buffer).collect();
- let fns = self.device.fns();
- fns.v1_0.free_command_buffers(
- self.device.internal_object(),
- self.pool,
- command_buffers.len() as u32,
- command_buffers.as_ptr(),
- )
- }
-
- /// Returns the queue family on which command buffers of this pool can be executed.
- #[inline]
- pub fn queue_family(&self) -> QueueFamily {
- self.device
- .physical_device()
- .queue_family_by_id(self.queue_family_index)
- .unwrap()
- }
-}
-
-unsafe impl DeviceOwned for UnsafeCommandPool {
- #[inline]
- fn device(&self) -> &Arc<Device> {
- &self.device
- }
-}
-
-unsafe impl VulkanObject for UnsafeCommandPool {
- type Object = ash::vk::CommandPool;
-
- #[inline]
- fn internal_object(&self) -> ash::vk::CommandPool {
- self.pool
- }
-}
-
-impl Drop for UnsafeCommandPool {
- #[inline]
- fn drop(&mut self) {
- unsafe {
- let fns = self.device.fns();
- fns.v1_0
- .destroy_command_pool(self.device.internal_object(), self.pool, ptr::null());
- }
- }
-}
-
-/// Opaque type that represents a command buffer allocated from a pool.
-pub struct UnsafeCommandPoolAlloc {
- command_buffer: ash::vk::CommandBuffer,
- device: Arc<Device>,
-}
-
-unsafe impl DeviceOwned for UnsafeCommandPoolAlloc {
- #[inline]
- fn device(&self) -> &Arc<Device> {
- &self.device
- }
-}
-
-unsafe impl VulkanObject for UnsafeCommandPoolAlloc {
- type Object = ash::vk::CommandBuffer;
-
- #[inline]
- fn internal_object(&self) -> ash::vk::CommandBuffer {
- self.command_buffer
- }
-}
-
-/// Iterator for newly-allocated command buffers.
-#[derive(Debug)]
-pub struct UnsafeCommandPoolAllocIter {
- device: Arc<Device>,
- list: VecIntoIter<ash::vk::CommandBuffer>,
-}
-
-impl Iterator for UnsafeCommandPoolAllocIter {
- type Item = UnsafeCommandPoolAlloc;
-
- #[inline]
- fn next(&mut self) -> Option<UnsafeCommandPoolAlloc> {
- self.list
- .next()
- .map(|command_buffer| UnsafeCommandPoolAlloc {
- command_buffer,
- device: self.device.clone(),
- })
- }
-
- #[inline]
- fn size_hint(&self) -> (usize, Option<usize>) {
- self.list.size_hint()
- }
-}
-
-impl ExactSizeIterator for UnsafeCommandPoolAllocIter {}
-
-/// Error that can happen when trimming command pools.
-#[derive(Copy, Clone, Debug, PartialEq, Eq)]
-pub enum CommandPoolTrimError {
- /// The `KHR_maintenance1` extension was not enabled.
- Maintenance1ExtensionNotEnabled,
-}
-
-impl error::Error for CommandPoolTrimError {}
-
-impl fmt::Display for CommandPoolTrimError {
- #[inline]
- fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
- write!(
- fmt,
- "{}",
- match *self {
- CommandPoolTrimError::Maintenance1ExtensionNotEnabled => {
- "the `KHR_maintenance1` extension was not enabled"
- }
- }
- )
- }
-}
-
-impl From<Error> for CommandPoolTrimError {
- #[inline]
- fn from(err: Error) -> CommandPoolTrimError {
- panic!("unexpected error: {:?}", err)
- }
-}
-
-#[cfg(test)]
-mod tests {
- use crate::command_buffer::pool::CommandPoolTrimError;
- use crate::command_buffer::pool::UnsafeCommandPool;
- use crate::Version;
-
- #[test]
- fn basic_create() {
- let (device, queue) = gfx_dev_and_queue!();
- let _ = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
- }
-
- #[test]
- fn queue_family_getter() {
- let (device, queue) = gfx_dev_and_queue!();
- let pool = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
- assert_eq!(pool.queue_family().id(), queue.family().id());
- }
-
- #[test]
- fn panic_if_not_match_family() {
- let (device, _) = gfx_dev_and_queue!();
- let (_, queue) = gfx_dev_and_queue!();
-
- assert_should_panic!(
- "Device doesn't match physical device when creating a command pool",
- {
- let _ = UnsafeCommandPool::new(device, queue.family(), false, false);
- }
- );
- }
-
- #[test]
- fn check_maintenance_when_trim() {
- let (device, queue) = gfx_dev_and_queue!();
- let pool = UnsafeCommandPool::new(device.clone(), queue.family(), false, false).unwrap();
-
- if device.api_version() >= Version::V1_1 {
- match pool.trim() {
- Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) => panic!(),
- _ => (),
- }
- } else {
- match pool.trim() {
- Err(CommandPoolTrimError::Maintenance1ExtensionNotEnabled) => (),
- _ => panic!(),
- }
- }
- }
-
- // TODO: test that trim works if VK_KHR_maintenance1 if enabled ; the test macro doesn't
- // support enabling extensions yet
-
- #[test]
- fn basic_alloc() {
- let (device, queue) = gfx_dev_and_queue!();
- let pool = UnsafeCommandPool::new(device, queue.family(), false, false).unwrap();
- let iter = pool.alloc_command_buffers(false, 12).unwrap();
- assert_eq!(iter.count(), 12);
- }
-}