Skip to main content

dacite/core/
command_pool.rs

1// Copyright (c) 2017, Dennis Hamester <dennis.hamester@startmail.com>
2//
3// Permission to use, copy, modify, and/or distribute this software for any
4// purpose with or without fee is hereby granted, provided that the above
5// copyright notice and this permission notice appear in all copies.
6//
7// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
8// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
9// FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
10// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
11// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
12// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
13// PERFORMANCE OF THIS SOFTWARE.
14
15use FromNativeObject;
16use TryDestroyError;
17use TryDestroyErrorKind;
18use VulkanObject;
19use core::allocator_helper::AllocatorHelper;
20use core::{self, CommandBuffer, Device};
21use std::cmp::Ordering;
22use std::hash::{Hash, Hasher};
23use std::ptr;
24use std::sync::Arc;
25use vks;
26
27/// See [`VkCommandPool`](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#VkCommandPool)
28#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
29pub struct CommandPool(Arc<Inner>);
30
31impl VulkanObject for CommandPool {
32    type NativeVulkanObject = vks::core::VkCommandPool;
33
34    #[inline]
35    fn id(&self) -> u64 {
36        self.handle()
37    }
38
39    #[inline]
40    fn as_native_vulkan_object(&self) -> Self::NativeVulkanObject {
41        self.handle()
42    }
43
44    fn try_destroy(self) -> Result<(), TryDestroyError<Self>> {
45        let strong_count = Arc::strong_count(&self.0);
46        if strong_count == 1 {
47            Ok(())
48        }
49        else {
50            Err(TryDestroyError::new(self, TryDestroyErrorKind::InUse(Some(strong_count))))
51        }
52    }
53}
54
55pub struct FromNativeCommandPoolParameters {
56    /// `true`, if this `CommandPool` should destroy the underlying Vulkan object, when it is dropped.
57    pub owned: bool,
58
59    /// The `Device`, from which this `CommandPool` was created.
60    pub device: Device,
61
62    /// An `Allocator` compatible with the one used to create this `CommandPool`.
63    ///
64    /// This parameter is ignored, if `owned` is `false`.
65    pub allocator: Option<Box<core::Allocator>>,
66}
67
68impl FromNativeCommandPoolParameters {
69    #[inline]
70    pub fn new(owned: bool, device: Device, allocator: Option<Box<core::Allocator>>) -> Self {
71        FromNativeCommandPoolParameters {
72            owned: owned,
73            device: device,
74            allocator: allocator,
75        }
76    }
77}
78
79impl FromNativeObject for CommandPool {
80    type Parameters = FromNativeCommandPoolParameters;
81
82    unsafe fn from_native_object(object: Self::NativeVulkanObject, params: Self::Parameters) -> Self {
83        CommandPool::new(object, params.owned, params.device, params.allocator.map(AllocatorHelper::new))
84    }
85}
86
87impl CommandPool {
88    pub(crate) fn new(handle: vks::core::VkCommandPool, owned: bool, device: Device, allocator: Option<AllocatorHelper>) -> Self {
89        CommandPool(Arc::new(Inner {
90            handle: handle,
91            owned: owned,
92            device: device,
93            allocator: allocator,
94        }))
95    }
96
97    #[inline]
98    pub(crate) fn handle(&self) -> vks::core::VkCommandPool {
99        self.0.handle
100    }
101
102    #[inline]
103    pub(crate) fn loader(&self) -> &vks::DeviceProcAddrLoader {
104        self.0.device.loader()
105    }
106
107    #[inline]
108    pub(crate) fn device_handle(&self) -> vks::core::VkDevice {
109        self.0.device.handle()
110    }
111
112    /// See [`vkResetCommandPool`](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#vkResetCommandPool)
113    pub fn reset(&self, flags: core::CommandPoolResetFlags) -> Result<(), core::Error> {
114        let res = unsafe {
115            self.loader().core.vkResetCommandPool(self.device_handle(), self.handle(), flags.bits())
116        };
117
118        if res == vks::core::VK_SUCCESS {
119            Ok(())
120        }
121        else {
122            Err(res.into())
123        }
124    }
125
126    /// See [`vkAllocateCommandBuffers`](https://www.khronos.org/registry/vulkan/specs/1.0-extensions/html/vkspec.html#vkAllocateCommandBuffers)
127    pub fn allocate_command_buffers(allocate_info: &core::CommandBufferAllocateInfo) -> Result<Vec<CommandBuffer>, core::Error> {
128        let command_pool = &allocate_info.command_pool;
129        let allocate_info_wrapper = core::VkCommandBufferAllocateInfoWrapper::new(allocate_info, true);
130
131        let mut command_buffers = Vec::with_capacity(allocate_info.command_buffer_count as usize);
132        let res = unsafe {
133            command_buffers.set_len(allocate_info.command_buffer_count as usize);
134            command_pool.loader().core.vkAllocateCommandBuffers(command_pool.device_handle(), &allocate_info_wrapper.vks_struct, command_buffers.as_mut_ptr())
135        };
136
137        if res == vks::core::VK_SUCCESS {
138            Ok(command_buffers.iter().map(|&c| CommandBuffer::new(c, true, command_pool.clone())).collect())
139        }
140        else {
141            Err(res.into())
142        }
143    }
144}
145
146#[derive(Debug)]
147struct Inner {
148    handle: vks::core::VkCommandPool,
149    owned: bool,
150    device: Device,
151    allocator: Option<AllocatorHelper>,
152}
153
154impl Drop for Inner {
155    fn drop(&mut self) {
156        if self.owned {
157            let allocator = match self.allocator {
158                Some(ref allocator) => allocator.callbacks(),
159                None => ptr::null(),
160            };
161
162            unsafe {
163                self.device.loader().core.vkDestroyCommandPool(self.device.handle(), self.handle, allocator);
164            }
165        }
166    }
167}
168
169unsafe impl Send for Inner { }
170
171unsafe impl Sync for Inner { }
172
173impl PartialEq for Inner {
174    #[inline]
175    fn eq(&self, other: &Self) -> bool {
176        self.handle == other.handle
177    }
178}
179
180impl Eq for Inner { }
181
182impl PartialOrd for Inner {
183    #[inline]
184    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
185        self.handle.partial_cmp(&other.handle)
186    }
187}
188
189impl Ord for Inner {
190    #[inline]
191    fn cmp(&self, other: &Self) -> Ordering {
192        self.handle.cmp(&other.handle)
193    }
194}
195
196impl Hash for Inner {
197    #[inline]
198    fn hash<H: Hasher>(&self, state: &mut H) {
199        self.handle.hash(state);
200    }
201}