vulkayes_core/queue/
mod.rs

1use std::{
2	fmt::{Debug, Formatter},
3	ops::Deref
4};
5
6use ash::{
7	version::{DeviceV1_0, DeviceV1_1},
8	vk::{self, DeviceQueueCreateFlags, DeviceQueueInfo2}
9};
10
11use crate::{device::Device, prelude::Vrc, sync::fence::Fence, util::sync::Vutex};
12
13#[macro_use]
14pub mod macros;
15
16pub mod error;
17pub mod sharing_mode;
18
19/// An internally synchronized device queue.
20pub struct Queue {
21	device: Vrc<Device>,
22	queue: Vutex<ash::vk::Queue>,
23
24	// TODO: Creation flags?
25	queue_family_index: u32,
26	queue_index: u32
27}
28impl Queue {
29	const_queue_submit! {
30		pub fn submit_one_fence_only(
31			&queue,
32			waits: [&Semaphore; 0],
33			stages: [vk::PipelineStageFlags; _],
34			buffers: [&CommandBuffer; 1],
35			signals: [&Semaphore; 0],
36			fence: Option<&Fence>
37		) -> Result<(), QueueSubmitError>;
38	}
39
40	const_queue_submit! {
41		/// Example submit function generated using the [const_queue_submit!](../macro.const_queue_submit.html) macro.
42		///
43		/// At some point in the distant future this function will become const generic and the macro will be an implementation detail.
44		pub fn submit_one(
45			&queue,
46			waits: [&Semaphore; 1],
47			stages: [vk::PipelineStageFlags; _],
48			buffers: [&CommandBuffer; 1],
49			signals: [&Semaphore; 1],
50			fence: Option<&Fence>
51		) -> Result<(), QueueSubmitError>;
52	}
53
54	const_queue_present! {
55		/// Example present function generated using the [const_queue_present!](../macro.const_queue_present.html) macro.
56		///
57		/// At some point in the distant future this function will become const generic and the macro will be an implementation detail.
58		pub fn present_one(
59			&queue,
60			waits: [&Semaphore; 1],
61			images: [&SwapchainImage; 1],
62			result_for_all: bool
63		) -> QueuePresentMultipleResult<[QueuePresentResult; _]>;
64	}
65
66	/// Gets a queue from the logical device.
67	///
68	/// ### Safety
69	///
70	/// * See <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetDeviceQueue.html>.
71	/// * See <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkGetDeviceQueue2.html>.
72	pub unsafe fn from_device(
73		device: Vrc<Device>,
74		flags: DeviceQueueCreateFlags,
75		queue_family_index: u32,
76		queue_index: u32
77	) -> Vrc<Self> {
78		log_trace_common!(
79			"Creating queue:",
80			device,
81			flags,
82			queue_family_index,
83			queue_index
84		);
85		let queue = if flags.is_empty() {
86			device.get_device_queue(queue_family_index, queue_index)
87		} else {
88			let mut mem = std::mem::MaybeUninit::uninit();
89
90			let info = DeviceQueueInfo2::builder()
91				.flags(flags)
92				.queue_family_index(queue_family_index)
93				.queue_index(queue_index);
94			device
95				.fp_v1_1()
96				.get_device_queue2(device.handle(), info.deref(), mem.as_mut_ptr());
97
98			mem.assume_init()
99		};
100
101		Vrc::new(Queue {
102			device,
103			queue: Vutex::new(queue),
104			queue_family_index,
105			queue_index
106		})
107	}
108
109	/// Submits to given queue.
110	///
111	/// ### Safety
112	///
113	/// See <https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkQueueSubmit.html>
114	///
115	/// ### Panic
116	///
117	/// This function will panic if the `Vutex` is poisoned.
118	pub unsafe fn submit(
119		&self,
120		infos: impl AsRef<[vk::SubmitInfo]>,
121		fence: Option<&Fence>
122	) -> Result<(), error::QueueSubmitError> {
123		let lock = self.queue.lock().expect("vutex poisoned");
124
125		log_trace_common!(
126			"Submitting on queue:",
127			self,
128			crate::util::fmt::format_handle(*lock),
129			infos.as_ref(),
130			fence
131		);
132
133		if let Some(fence) = fence {
134			let fence_lock = fence.lock().expect("vutex poisoned");
135			self.device
136				.queue_submit(*lock, infos.as_ref(), *fence_lock)
137				.map_err(Into::into)
138		} else {
139			self.device
140				.queue_submit(*lock, infos.as_ref(), vk::Fence::null())
141				.map_err(Into::into)
142		}
143	}
144
145	/// Waits until all outstanding operations on the queue are completed.
146	///
147	/// ### Panic
148	///
149	/// This function will panic if the `Vutex` is poisoned.
150	pub fn wait(&self) -> Result<(), error::QueueWaitError> {
151		let lock = self.queue.lock().expect("vutex poisoned");
152
153		unsafe { self.device.queue_wait_idle(*lock).map_err(Into::into) }
154	}
155
156	pub const fn device(&self) -> &Vrc<Device> {
157		&self.device
158	}
159
160	pub const fn queue_family_index(&self) -> u32 {
161		self.queue_family_index
162	}
163
164	pub const fn queue_index(&self) -> u32 {
165		self.queue_index
166	}
167}
168impl_common_handle_traits! {
169	impl HasSynchronizedHandle<vk::Queue>, Deref, Borrow, Eq, Hash, Ord for Queue {
170		target = { queue }
171	}
172}
173impl Debug for Queue {
174	fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
175		f.debug_struct("Queue")
176			.field("device", &self.device)
177			.field("queue", &self.queue)
178			.field("queue_family_index", &self.queue_family_index)
179			.field("queue_index", &self.queue_index)
180			.finish()
181	}
182}