1use crate::{CommandBuffer, Device, DeviceOwned, ALLOCATION_CALLBACK_NONE};
2use ash::{
3 prelude::VkResult,
4 vk::{self, Handle},
5};
6use std::sync::Arc;
7
8pub struct CommandPool {
9 handle: vk::CommandPool,
10 properties: CommandPoolProperties,
11
12 device: Arc<Device>,
14}
15
16impl CommandPool {
17 pub fn new(device: Arc<Device>, properties: CommandPoolProperties) -> VkResult<Self> {
18 let create_info_builder = properties.create_info_builder();
19
20 let handle = unsafe {
21 device
22 .inner()
23 .create_command_pool(&create_info_builder, ALLOCATION_CALLBACK_NONE)
24 }?;
25
26 Ok(Self {
27 handle,
28 properties,
29 device,
30 })
31 }
32
33 pub unsafe fn new_from_create_info(
34 device: Arc<Device>,
35 create_info_builder: vk::CommandPoolCreateInfoBuilder,
36 ) -> VkResult<Self> {
37 let properties = CommandPoolProperties::from_create_info_builder(&create_info_builder);
38
39 let handle = unsafe {
40 device
41 .inner()
42 .create_command_pool(&create_info_builder, ALLOCATION_CALLBACK_NONE)
43 }?;
44
45 Ok(Self {
46 handle,
47 properties,
48 device,
49 })
50 }
51
52 pub fn allocate_command_buffers(
53 self: &Arc<Self>,
54 level: vk::CommandBufferLevel,
55 command_buffer_count: u32,
56 ) -> VkResult<Vec<CommandBuffer>> {
57 let allocate_info_builder = vk::CommandBufferAllocateInfo::builder()
58 .level(level)
59 .command_buffer_count(command_buffer_count)
60 .command_pool(self.handle);
61
62 unsafe { self.allocate_command_buffers_from_allocate_info(allocate_info_builder) }
63 }
64
65 #[inline]
66 pub fn allocate_command_buffer(
67 self: &Arc<Self>,
68 level: vk::CommandBufferLevel,
69 ) -> VkResult<CommandBuffer> {
70 let mut vec = self.allocate_command_buffers(level, 1)?;
71 Ok(vec.remove(0))
72 }
73
74 pub unsafe fn allocate_command_buffers_from_allocate_info(
75 self: &Arc<Self>,
76 allocate_info_builder: vk::CommandBufferAllocateInfoBuilder,
77 ) -> VkResult<Vec<CommandBuffer>> {
78 let level = allocate_info_builder.level;
79
80 let command_buffer_handles = unsafe {
81 self.device()
82 .inner()
83 .allocate_command_buffers(&allocate_info_builder)
84 }?;
85
86 let command_buffers: Vec<CommandBuffer> = command_buffer_handles
87 .into_iter()
88 .map(|handle| unsafe { CommandBuffer::from_handle(handle, level, self.clone()) })
89 .collect();
90 Ok(command_buffers)
91 }
92
93 pub fn reset(&self, reset_flags: vk::CommandPoolResetFlags) -> VkResult<()> {
94 unsafe {
95 self.device
96 .inner()
97 .reset_command_pool(self.handle, reset_flags)
98 }
99 }
100
101 pub fn handle(&self) -> vk::CommandPool {
104 self.handle
105 }
106
107 pub fn properties(&self) -> CommandPoolProperties {
108 self.properties
109 }
110}
111
112impl DeviceOwned for CommandPool {
113 #[inline]
114 fn device(&self) -> &Arc<Device> {
115 &self.device
116 }
117
118 #[inline]
119 fn handle_raw(&self) -> u64 {
120 self.handle.as_raw()
121 }
122}
123
124impl Drop for CommandPool {
125 fn drop(&mut self) {
126 unsafe {
127 self.device
128 .inner()
129 .destroy_command_pool(self.handle, ALLOCATION_CALLBACK_NONE);
130 }
131 }
132}
133
134#[derive(Default, Clone, Copy)]
138pub struct CommandPoolProperties {
139 pub flags: vk::CommandPoolCreateFlags,
140 pub queue_family_index: u32,
141}
142
143impl CommandPoolProperties {
144 pub fn new_default(queue_family_index: u32) -> Self {
145 Self {
146 queue_family_index,
147 ..Default::default()
148 }
149 }
150
151 pub fn write_create_info_builder<'a>(
152 &self,
153 builder: vk::CommandPoolCreateInfoBuilder<'a>,
154 ) -> vk::CommandPoolCreateInfoBuilder<'a> {
155 builder
156 .flags(self.flags)
157 .queue_family_index(self.queue_family_index)
158 }
159
160 pub fn create_info_builder(&self) -> vk::CommandPoolCreateInfoBuilder {
161 self.write_create_info_builder(vk::CommandPoolCreateInfo::builder())
162 }
163
164 pub fn from_create_info_builder(value: &vk::CommandPoolCreateInfoBuilder) -> Self {
165 Self {
166 flags: value.flags,
167
168 queue_family_index: value.queue_family_index,
170 }
171 }
172}