bort_vk/
command_pool.rs

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    // dependencies
13    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    // Getters
102
103    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// Properties
135
136/// Note: default value for `queue_family_index` is nothing!
137#[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            // nonsense defaults. make sure you override these!
169            queue_family_index: value.queue_family_index,
170        }
171    }
172}