1use crate::{
2 ApiVersion, DebugCallback, Fence, Instance, PhysicalDevice, Queue, ALLOCATION_CALLBACK_NONE,
3};
4use ash::{
5 prelude::VkResult,
6 vk::{self, DeviceQueueCreateInfo, ExtendsDeviceCreateInfo},
7};
8use std::{
9 error,
10 ffi::{CString, NulError},
11 fmt,
12 os::raw::c_char,
13 sync::Arc,
14};
15
16pub trait DeviceOwned {
17 fn device(&self) -> &Arc<Device>;
18 fn handle_raw(&self) -> u64;
19}
20
21pub struct Device {
22 inner: ash::Device,
23 debug_callback_ref: Option<Arc<DebugCallback>>,
24
25 physical_device: Arc<PhysicalDevice>,
27}
28
29impl Device {
30 pub fn new<'a>(
33 physical_device: Arc<PhysicalDevice>,
34 queue_create_infos: impl IntoIterator<Item = vk::DeviceQueueCreateInfoBuilder<'a>>,
35 features_1_0: vk::PhysicalDeviceFeatures,
36 features_1_1: vk::PhysicalDeviceVulkan11Features,
37 features_1_2: vk::PhysicalDeviceVulkan12Features,
38 features_1_3: vk::PhysicalDeviceVulkan13Features,
39 extension_names: Vec<CString>,
40 layer_names: Vec<CString>,
41 debug_callback_ref: Option<Arc<DebugCallback>>,
42 ) -> Result<Self, DeviceError> {
43 let queue_create_infos_built: Vec<DeviceQueueCreateInfo> = queue_create_infos
44 .into_iter()
45 .map(move |create_info| create_info.build())
46 .collect();
47 unsafe {
48 Self::new_with_p_next_chain(
49 physical_device,
50 &queue_create_infos_built,
51 features_1_0,
52 features_1_1,
53 features_1_2,
54 features_1_3,
55 extension_names,
56 layer_names,
57 debug_callback_ref,
58 Vec::<vk::PhysicalDeviceFeatures2>::new(),
59 )
60 }
61 }
62
63 pub unsafe fn new_with_p_next_chain<'a>(
74 physical_device: Arc<PhysicalDevice>,
75 queue_create_infos: &'a [vk::DeviceQueueCreateInfo],
76 features_1_0: vk::PhysicalDeviceFeatures,
77 mut features_1_1: vk::PhysicalDeviceVulkan11Features,
78 mut features_1_2: vk::PhysicalDeviceVulkan12Features,
79 mut features_1_3: vk::PhysicalDeviceVulkan13Features,
80 extension_names: Vec<CString>,
81 layer_names: Vec<CString>,
82 debug_callback_ref: Option<Arc<DebugCallback>>,
83 mut p_next_structs: Vec<impl ExtendsDeviceCreateInfo>,
84 ) -> Result<Self, DeviceError> {
85 let instance = physical_device.instance();
86
87 let extension_name_ptrs: Vec<*const c_char> = extension_names
88 .iter()
89 .map(|cstring| cstring.as_ptr())
90 .collect();
91 let layer_name_ptrs: Vec<*const c_char> =
92 layer_names.iter().map(|cstring| cstring.as_ptr()).collect();
93
94 #[allow(deprecated)] let mut device_create_info = vk::DeviceCreateInfo::builder()
96 .queue_create_infos(queue_create_infos)
97 .enabled_extension_names(&extension_name_ptrs)
98 .enabled_layer_names(&layer_name_ptrs);
99
100 let mut features_2 = vk::PhysicalDeviceFeatures2::builder();
101 let max_api_version = instance.max_api_version();
102
103 if max_api_version <= ApiVersion::new(1, 0) {
104 device_create_info = device_create_info.enabled_features(&features_1_0);
105 } else {
106 features_2 = features_2.features(features_1_0);
107 device_create_info = device_create_info.push_next(&mut features_2);
108
109 if max_api_version >= ApiVersion::new(1, 1) {
110 device_create_info = device_create_info.push_next(&mut features_1_1)
111 }
112 if max_api_version >= ApiVersion::new(1, 2) {
113 device_create_info = device_create_info.push_next(&mut features_1_2);
114 }
115 if max_api_version >= ApiVersion::new(1, 3) {
116 device_create_info = device_create_info.push_next(&mut features_1_3);
117 }
118 }
119
120 for p_next_struct in &mut p_next_structs {
121 device_create_info = device_create_info.push_next(p_next_struct);
122 }
123
124 Self::new_from_create_info(physical_device, device_create_info, debug_callback_ref)
125 }
126
127 pub unsafe fn new_from_create_info(
130 physical_device: Arc<PhysicalDevice>,
131 create_info_builder: vk::DeviceCreateInfoBuilder,
132 debug_callback_ref: Option<Arc<DebugCallback>>,
133 ) -> Result<Self, DeviceError> {
134 let inner = unsafe {
135 physical_device.instance().inner().create_device(
136 physical_device.handle(),
137 &create_info_builder,
138 ALLOCATION_CALLBACK_NONE,
139 )
140 }
141 .map_err(|vk_res| DeviceError::Creation(vk_res))?;
142
143 Ok(Self {
144 inner,
145 debug_callback_ref,
146 physical_device,
147 })
148 }
149
150 pub fn set_debug_callback_ref(&mut self, debug_callback_ref: Option<Arc<DebugCallback>>) {
154 self.debug_callback_ref = debug_callback_ref;
155 }
156
157 pub fn wait_idle(&self) -> Result<(), DeviceError> {
159 let res = unsafe { self.inner.device_wait_idle() };
160 res.map_err(|vk_res| DeviceError::WaitIdle(vk_res))
161 }
162
163 pub fn queue_wait_idle(&self, queue: &Queue) -> Result<(), DeviceError> {
165 let res = unsafe { self.inner.queue_wait_idle(queue.handle()) };
166 res.map_err(|vk_res| DeviceError::WaitIdle(vk_res))
167 }
168
169 pub fn update_descriptor_sets<'a>(
171 &self,
172 descriptor_writes: impl IntoIterator<Item = vk::WriteDescriptorSetBuilder<'a>>,
173 descriptor_copies: impl IntoIterator<Item = vk::CopyDescriptorSetBuilder<'a>>,
174 ) {
175 let descriptor_writes_built: Vec<vk::WriteDescriptorSet> = descriptor_writes
176 .into_iter()
177 .map(|descriptor_write| descriptor_write.build())
178 .collect();
179 let descriptor_copies_built: Vec<vk::CopyDescriptorSet> = descriptor_copies
180 .into_iter()
181 .map(|descriptor_copy| descriptor_copy.build())
182 .collect();
183 unsafe {
184 self.inner
185 .update_descriptor_sets(&descriptor_writes_built, &descriptor_copies_built)
186 }
187 }
188
189 pub fn wait_for_fences<'a>(
191 &self,
192 fences: impl IntoIterator<Item = &'a Fence>,
193 wait_all: bool,
194 timeout: u64,
195 ) -> VkResult<()> {
196 let fence_hanles: Vec<vk::Fence> = fences.into_iter().map(|fence| fence.handle()).collect();
197 unsafe { self.inner.wait_for_fences(&fence_hanles, wait_all, timeout) }
198 }
199
200 #[inline]
205 pub fn inner(&self) -> &ash::Device {
206 &self.inner
207 }
208
209 #[inline]
210 pub fn physical_device(&self) -> &Arc<PhysicalDevice> {
211 &self.physical_device
212 }
213
214 #[inline]
215 pub fn instance(&self) -> &Arc<Instance> {
216 self.physical_device.instance()
217 }
218
219 #[inline]
220 pub fn debug_callback_ref(&self) -> &Option<Arc<DebugCallback>> {
221 &self.debug_callback_ref
222 }
223}
224
225impl Drop for Device {
226 fn drop(&mut self) {
227 self.wait_idle().expect("vkDeviceWaitIdle");
228 unsafe {
229 self.inner.destroy_device(ALLOCATION_CALLBACK_NONE);
230 }
231 }
232}
233
234#[derive(Debug, Clone)]
235pub enum DeviceError {
236 ExtensionStringConversion(NulError),
237 LayerStringConversion(NulError),
238 Creation(vk::Result),
239 WaitIdle(vk::Result),
240}
241
242impl fmt::Display for DeviceError {
243 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
244 match self {
245 Self::ExtensionStringConversion(e) => {
246 write!(
247 f,
248 "failed to convert extension name string to c string: {}",
249 e
250 )
251 }
252 Self::LayerStringConversion(e) => {
253 write!(f, "failed to convert layer name string to c string: {}", e)
254 }
255 Self::Creation(e) => write!(f, "failed to create device: {}", e),
256 Self::WaitIdle(e) => write!(f, "vkDeviceWaitIdle call failed: {}", e),
257 }
258 }
259}
260
261impl error::Error for DeviceError {
262 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
263 match self {
264 Self::ExtensionStringConversion(e) => Some(e),
265 Self::LayerStringConversion(e) => Some(e),
266 Self::Creation(e) => Some(e),
267 Self::WaitIdle(e) => Some(e),
268 }
269 }
270}