use crate::prelude::*; use anyhow::Result; use std::{ slice, sync::{Arc, Mutex}, time::Duration, }; pub struct QueueRequestInfo { pub queue_create_info: VkDeviceQueueCreateInfo, pub queue_family_index: u32, pub queue_index: u32, } #[derive(Debug)] pub struct Queue { device: Arc, queue: VkQueue, family_index: u32, queue_index: u32, } impl Queue { pub fn create_presentable_request_info( physical_device: &Arc, surface: &Arc, queue_type: impl Into, ) -> Result { let index = Self::find_presentable_queue_index(physical_device, surface, queue_type.into())?; let priorities = &[0.0f32]; Ok(QueueRequestInfo { queue_create_info: VkDeviceQueueCreateInfo::new(0, index, priorities), queue_family_index: index, queue_index: 0, }) } pub fn create_non_presentable_request_info( physical_device: &Arc, queue_type: impl Into, ) -> Result { let index = Self::find_non_presentable_queue_index(physical_device, queue_type.into())?; let priorities = &[0.0f32]; Ok(QueueRequestInfo { queue_create_info: VkDeviceQueueCreateInfo::new(0, index, priorities), queue_family_index: index, queue_index: 0, }) } pub fn new( device: Arc, queue: VkQueue, family_index: u32, queue_index: u32, ) -> Arc> { Arc::new(Mutex::new(Queue { device, queue, family_index, queue_index, })) } pub fn family_index(&self) -> u32 { self.family_index } pub fn queue_index(&self) -> u32 { self.queue_index } /// really expensiv call, since its locks the queue until it is idle pub fn submit(&self, fence: Option<&Arc>, submits: &[SubmitInfo]) -> Result<()> { let submit_infos: Vec = submits.iter().map(|s| s.as_vk_submit()).collect(); let fence = match fence { Some(fence) => fence.vk_handle(), None => VkFence::NULL_HANDLE, }; self.device .queue_submit(self.queue, submit_infos.as_slice(), fence) } pub fn minimal_submit( &self, time_out: Duration, command_buffers: &[Arc], ) -> Result<()> { let mut submit = SubmitInfo::default(); for command_buffer in command_buffers.iter() { submit = submit.add_command_buffer(command_buffer); } let fence = Fence::builder().build(self.device.clone())?; self.submit(Some(&fence), slice::from_ref(&submit))?; // make sure command_buffer is ready self.device.wait_for_fences(&[&fence], true, time_out)?; Ok(()) } pub fn present( &self, swapchains: &[&Arc], image_indices: &[u32], wait_semaphores: &[&Arc], ) -> Result> { let wait_semaphores: Vec = wait_semaphores.iter().map(|sem| sem.vk_handle()).collect(); let swapchains: Vec = swapchains .iter() .map(|swapchain| swapchain.vk_handle()) .collect(); let present_info = VkPresentInfoKHR::new( wait_semaphores.as_slice(), swapchains.as_slice(), image_indices, &mut [], ); self.device.queue_present(self.queue, &present_info) } pub fn wait_idle(&self) -> Result<()> { self.device.queue_wait_idle(self.queue) } } impl VulkanDevice for Queue { fn device(&self) -> &Arc { &self.device } } impl_vk_handle!(Queue, VkQueue, queue); impl Queue { fn find_presentable_queue_index( physical_device: &Arc, surface: &Arc, flags: VkQueueFlagBits, ) -> Result { let surface = surface.vk_handle(); let vk_physical_device = physical_device.vk_handle(); let queue_family_properties = physical_device .instance() .physical_device_queue_family_properties(vk_physical_device); for (i, queue) in queue_family_properties.iter().enumerate() { if (queue.queueFlagBits & flags) == flags { let presentable = physical_device.instance().physical_device_surface_support( vk_physical_device, i as u32, surface, )?; if presentable { return Ok(i as u32); } } } Err(anyhow::Error::msg("Requested queue could not be found")) } fn find_non_presentable_queue_index( physical_device: &Arc, flags: VkQueueFlagBits, ) -> Result { let vk_physical_device = physical_device.vk_handle(); let queue_family_properties = physical_device .instance() .physical_device_queue_family_properties(vk_physical_device); for (i, queue) in queue_family_properties.iter().enumerate() { if (queue.queueFlagBits & flags) == flags { return Ok(i as u32); } } Err(anyhow::Error::msg("Requested queue could not be found")) } } #[derive(Default)] pub struct SubmitInfo { wait_semaphores: Vec, wait_stages: Vec, command_buffers: Vec, signal_semaphores: Vec, } impl SubmitInfo { pub fn add_wait_semaphore( self, wait_semaphore: impl VkHandle, wait_stage: impl Into, ) -> Self { self.add_wait_semaphore_vk(wait_semaphore.vk_handle(), wait_stage) } pub fn add_wait_semaphore_vk( mut self, wait_semaphore: VkSemaphore, wait_stage: impl Into, ) -> Self { self.wait_semaphores.push(wait_semaphore); self.wait_stages.push(wait_stage.into()); self } pub fn add_command_buffer(mut self, command_buffer: impl VkHandle) -> Self { self.command_buffers.push(command_buffer.vk_handle()); self } pub fn add_signal_semaphore(self, signal_semaphore: impl VkHandle) -> Self { self.add_signal_semaphore_vk(signal_semaphore.vk_handle()) } pub fn add_signal_semaphore_vk(mut self, signal_semaphore: VkSemaphore) -> Self { self.signal_semaphores.push(signal_semaphore); self } pub fn as_vk_submit(&self) -> VkSubmitInfo { VkSubmitInfo::new( self.wait_semaphores.as_slice(), self.wait_stages.as_slice(), self.command_buffers.as_slice(), self.signal_semaphores.as_slice(), ) } }