use crate::vulkan::{VkInstance, VkPhysicalDevice}; use ash::prelude::VkResult; use ash::vk; use std::sync::Arc; pub struct VkDevice { instance: Arc, pub(super) handle: ash::Device, pub(super) swapchain_loader: ash::khr::swapchain::Device, pub(super) queue_family_index: u32, // Arc not used because vk::Queue is destroyed with Device automatically // so any references of vk::Queue must be destroyed with VkDevice queues: Vec, } impl VkDevice { pub(super) fn new_graphics_device( instance: &Arc, physical_device: &VkPhysicalDevice, queue_family_index: u32, ) -> anyhow::Result { let device_extension_names_raw = [ ash::khr::swapchain::NAME.as_ptr(), #[cfg(any(target_os = "macos", target_os = "ios"))] ash::khr::portability_subset::NAME.as_ptr(), ]; let features = vk::PhysicalDeviceFeatures { shader_clip_distance: 1, ..Default::default() }; let queues_priorities = [1.0]; let queue_info = vk::DeviceQueueCreateInfo::default() .queue_family_index(queue_family_index) .queue_priorities(&queues_priorities); let device_create_info = vk::DeviceCreateInfo::default() .queue_create_infos(std::slice::from_ref(&queue_info)) .enabled_extension_names(&device_extension_names_raw) .enabled_features(&features); let device = unsafe { instance .handle .create_device(physical_device.handle, &device_create_info, None)? }; log::debug!("Device created ({:?})", device.handle()); let queues = queues_priorities .iter() .enumerate() .map(|(index, _)| unsafe { device.get_device_queue(queue_family_index, index as u32) }) .collect::>(); let swapchain_loader = ash::khr::swapchain::Device::new(&instance.handle, &device); Ok(Self { instance: instance.clone(), handle: device, swapchain_loader, queue_family_index, queues, }) } pub(super) fn get_device_queue(&self, queue_index: u32) -> Option<&vk::Queue> { self.queues.get(queue_index as usize) } pub(super) fn create_command_pool( &self, info: &vk::CommandPoolCreateInfo, ) -> VkResult { let info = info.queue_family_index(self.queue_family_index); unsafe { self.handle.create_command_pool(&info, None) } } pub(super) fn allocate_command_buffers( &self, info: &vk::CommandBufferAllocateInfo, ) -> VkResult> { unsafe { self.handle.allocate_command_buffers(&info) } } pub(super) fn create_fence(&self, info: &vk::FenceCreateInfo) -> VkResult { unsafe { self.handle.create_fence(&info, None) } } pub(super) fn create_semaphore( &self, info: &vk::SemaphoreCreateInfo, ) -> VkResult { unsafe { self.handle.create_semaphore(&info, None) } } } impl Drop for VkDevice { fn drop(&mut self) { unsafe { self.handle.destroy_device(None); log::debug!("Device destroyed ({:?})", self.handle.handle()); } } }