rafx_api/
queue.rs

1#[cfg(feature = "rafx-dx12")]
2use crate::dx12::RafxQueueDx12;
3#[cfg(any(
4    feature = "rafx-empty",
5    not(any(
6        feature = "rafx-dx12",
7        feature = "rafx-metal",
8        feature = "rafx-vulkan",
9        feature = "rafx-gles2",
10        feature = "rafx-gles3"
11    ))
12))]
13use crate::empty::RafxQueueEmpty;
14#[cfg(feature = "rafx-gles2")]
15use crate::gles2::RafxQueueGles2;
16#[cfg(feature = "rafx-gles3")]
17use crate::gles3::RafxQueueGles3;
18#[cfg(feature = "rafx-metal")]
19use crate::metal::RafxQueueMetal;
20#[cfg(feature = "rafx-vulkan")]
21use crate::vulkan::RafxQueueVulkan;
22use crate::{
23    RafxCommandBuffer, RafxCommandPool, RafxCommandPoolDef, RafxDeviceContext, RafxFence,
24    RafxPresentSuccessResult, RafxQueueType, RafxResult, RafxSemaphore, RafxSwapchain,
25};
26
27/// A queue allows work to be submitted to the GPU
28///
29/// Work that has been submitted to the same queue has some ordering guarantees.
30///
31/// Resources may only be accessed from one queue type at a time. If a resource is to be used by
32/// a different queue, a memory barrier on both the "sending" and "receiving" queue is required.
33///
34/// The default configuration is to return the same underlying queue every time create_queue() is
35/// called. A mutex protects against multiple threads submitting work to the queue at the same time.
36///
37/// Most applications can just create and use graphics queues freely, relying on the API returning
38/// the same underlying queue every time.
39#[derive(Clone, Debug)]
40pub enum RafxQueue {
41    #[cfg(feature = "rafx-dx12")]
42    Dx12(RafxQueueDx12),
43    #[cfg(feature = "rafx-vulkan")]
44    Vk(RafxQueueVulkan),
45    #[cfg(feature = "rafx-metal")]
46    Metal(RafxQueueMetal),
47    #[cfg(feature = "rafx-gles2")]
48    Gles2(RafxQueueGles2),
49    #[cfg(feature = "rafx-gles3")]
50    Gles3(RafxQueueGles3),
51    #[cfg(any(
52        feature = "rafx-empty",
53        not(any(
54            feature = "rafx-dx12",
55            feature = "rafx-metal",
56            feature = "rafx-vulkan",
57            feature = "rafx-gles2",
58            feature = "rafx-gles3"
59        ))
60    ))]
61    Empty(RafxQueueEmpty),
62}
63
64impl RafxQueue {
65    pub fn device_context(&self) -> RafxDeviceContext {
66        match self {
67            #[cfg(feature = "rafx-dx12")]
68            RafxQueue::Dx12(inner) => RafxDeviceContext::Dx12(inner.device_context().clone()),
69            #[cfg(feature = "rafx-vulkan")]
70            RafxQueue::Vk(inner) => RafxDeviceContext::Vk(inner.device_context().clone()),
71            #[cfg(feature = "rafx-metal")]
72            RafxQueue::Metal(inner) => RafxDeviceContext::Metal(inner.device_context().clone()),
73            #[cfg(feature = "rafx-gles2")]
74            RafxQueue::Gles2(inner) => RafxDeviceContext::Gles2(inner.device_context().clone()),
75            #[cfg(feature = "rafx-gles3")]
76            RafxQueue::Gles3(inner) => RafxDeviceContext::Gles3(inner.device_context().clone()),
77            #[cfg(any(
78                feature = "rafx-empty",
79                not(any(
80                    feature = "rafx-dx12",
81                    feature = "rafx-metal",
82                    feature = "rafx-vulkan",
83                    feature = "rafx-gles2",
84                    feature = "rafx-gles3"
85                ))
86            ))]
87            RafxQueue::Empty(inner) => RafxDeviceContext::Empty(inner.device_context().clone()),
88        }
89    }
90
91    /// Returns an opaque ID associated with this queue. It may be used to hash which queue a
92    /// command pool is associated with
93    pub fn queue_id(&self) -> u32 {
94        match self {
95            #[cfg(feature = "rafx-dx12")]
96            RafxQueue::Dx12(inner) => inner.queue_id(),
97            #[cfg(feature = "rafx-vulkan")]
98            RafxQueue::Vk(inner) => inner.queue_id(),
99            #[cfg(feature = "rafx-metal")]
100            RafxQueue::Metal(inner) => inner.queue_id(),
101            #[cfg(feature = "rafx-gles2")]
102            RafxQueue::Gles2(inner) => inner.queue_id(),
103            #[cfg(feature = "rafx-gles3")]
104            RafxQueue::Gles3(inner) => inner.queue_id(),
105            #[cfg(any(
106                feature = "rafx-empty",
107                not(any(
108                    feature = "rafx-dx12",
109                    feature = "rafx-metal",
110                    feature = "rafx-vulkan",
111                    feature = "rafx-gles2",
112                    feature = "rafx-gles3"
113                ))
114            ))]
115            RafxQueue::Empty(inner) => inner.queue_id(),
116        }
117    }
118
119    /// Get the type of queue that this is
120    pub fn queue_type(&self) -> RafxQueueType {
121        match self {
122            #[cfg(feature = "rafx-dx12")]
123            RafxQueue::Dx12(inner) => inner.queue_type(),
124            #[cfg(feature = "rafx-vulkan")]
125            RafxQueue::Vk(inner) => inner.queue_type(),
126            #[cfg(feature = "rafx-metal")]
127            RafxQueue::Metal(inner) => inner.queue_type(),
128            #[cfg(feature = "rafx-gles2")]
129            RafxQueue::Gles2(inner) => inner.queue_type(),
130            #[cfg(feature = "rafx-gles3")]
131            RafxQueue::Gles3(inner) => inner.queue_type(),
132            #[cfg(any(
133                feature = "rafx-empty",
134                not(any(
135                    feature = "rafx-dx12",
136                    feature = "rafx-metal",
137                    feature = "rafx-vulkan",
138                    feature = "rafx-gles2",
139                    feature = "rafx-gles3"
140                ))
141            ))]
142            RafxQueue::Empty(inner) => inner.queue_type(),
143        }
144    }
145
146    /// Create a command pool for use with this queue
147    pub fn create_command_pool(
148        &self,
149        command_pool_def: &RafxCommandPoolDef,
150    ) -> RafxResult<RafxCommandPool> {
151        Ok(match self {
152            #[cfg(feature = "rafx-dx12")]
153            RafxQueue::Dx12(inner) => {
154                RafxCommandPool::Dx12(inner.create_command_pool(command_pool_def)?)
155            }
156            #[cfg(feature = "rafx-vulkan")]
157            RafxQueue::Vk(inner) => {
158                RafxCommandPool::Vk(inner.create_command_pool(command_pool_def)?)
159            }
160            #[cfg(feature = "rafx-metal")]
161            RafxQueue::Metal(inner) => {
162                RafxCommandPool::Metal(inner.create_command_pool(command_pool_def)?)
163            }
164            #[cfg(feature = "rafx-gles2")]
165            RafxQueue::Gles2(inner) => {
166                RafxCommandPool::Gles2(inner.create_command_pool(command_pool_def)?)
167            }
168            #[cfg(feature = "rafx-gles3")]
169            RafxQueue::Gles3(inner) => {
170                RafxCommandPool::Gles3(inner.create_command_pool(command_pool_def)?)
171            }
172            #[cfg(any(
173                feature = "rafx-empty",
174                not(any(
175                    feature = "rafx-dx12",
176                    feature = "rafx-metal",
177                    feature = "rafx-vulkan",
178                    feature = "rafx-gles2",
179                    feature = "rafx-gles3"
180                ))
181            ))]
182            RafxQueue::Empty(inner) => {
183                RafxCommandPool::Empty(inner.create_command_pool(command_pool_def)?)
184            }
185        })
186    }
187
188    /// Submit command buffers for processing by the GPU.
189    ///
190    /// Execution will not begin until all `wait_semaphores` are signaled.
191    ///
192    /// After execution, the given `signal_semaphores` and `signal_fence` are signaled as completed.
193    pub fn submit(
194        &self,
195        command_buffers: &[&RafxCommandBuffer],
196        wait_semaphores: &[&RafxSemaphore],
197        signal_semaphores: &[&RafxSemaphore],
198        signal_fence: Option<&RafxFence>,
199    ) -> RafxResult<()> {
200        match self {
201            #[cfg(feature = "rafx-dx12")]
202            RafxQueue::Dx12(inner) => {
203                let command_buffers: Vec<_> = command_buffers
204                    .iter()
205                    .map(|x| x.dx12_command_buffer().unwrap())
206                    .collect();
207                let wait_semaphores: Vec<_> = wait_semaphores
208                    .iter()
209                    .map(|x| x.dx12_semaphore().unwrap())
210                    .collect();
211                let signal_semaphores: Vec<_> = signal_semaphores
212                    .iter()
213                    .map(|x| x.dx12_semaphore().unwrap())
214                    .collect();
215                inner.submit(
216                    &command_buffers,
217                    &wait_semaphores,
218                    &signal_semaphores,
219                    signal_fence.map(|x| x.dx12_fence().unwrap()),
220                )
221            }
222            #[cfg(feature = "rafx-vulkan")]
223            RafxQueue::Vk(inner) => {
224                let command_buffers: Vec<_> = command_buffers
225                    .iter()
226                    .map(|x| x.vk_command_buffer().unwrap())
227                    .collect();
228                let wait_semaphores: Vec<_> = wait_semaphores
229                    .iter()
230                    .map(|x| x.vk_semaphore().unwrap())
231                    .collect();
232                let signal_semaphores: Vec<_> = signal_semaphores
233                    .iter()
234                    .map(|x| x.vk_semaphore().unwrap())
235                    .collect();
236                inner.submit(
237                    &command_buffers,
238                    &wait_semaphores,
239                    &signal_semaphores,
240                    signal_fence.map(|x| x.vk_fence().unwrap()),
241                )
242            }
243            #[cfg(feature = "rafx-metal")]
244            RafxQueue::Metal(inner) => {
245                let command_buffers: Vec<_> = command_buffers
246                    .iter()
247                    .map(|x| x.metal_command_buffer().unwrap())
248                    .collect();
249                let wait_semaphores: Vec<_> = wait_semaphores
250                    .iter()
251                    .map(|x| x.metal_semaphore().unwrap())
252                    .collect();
253                let signal_semaphores: Vec<_> = signal_semaphores
254                    .iter()
255                    .map(|x| x.metal_semaphore().unwrap())
256                    .collect();
257                inner.submit(
258                    &command_buffers,
259                    &wait_semaphores,
260                    &signal_semaphores,
261                    signal_fence.map(|x| x.metal_fence().unwrap()),
262                )
263            }
264            #[cfg(feature = "rafx-gles2")]
265            RafxQueue::Gles2(inner) => {
266                let command_buffers: Vec<_> = command_buffers
267                    .iter()
268                    .map(|x| x.gles2_command_buffer().unwrap())
269                    .collect();
270                let wait_semaphores: Vec<_> = wait_semaphores
271                    .iter()
272                    .map(|x| x.gles2_semaphore().unwrap())
273                    .collect();
274                let signal_semaphores: Vec<_> = signal_semaphores
275                    .iter()
276                    .map(|x| x.gles2_semaphore().unwrap())
277                    .collect();
278                inner.submit(
279                    &command_buffers,
280                    &wait_semaphores,
281                    &signal_semaphores,
282                    signal_fence.map(|x| x.gles2_fence().unwrap()),
283                )
284            }
285            #[cfg(feature = "rafx-gles3")]
286            RafxQueue::Gles3(inner) => {
287                let command_buffers: Vec<_> = command_buffers
288                    .iter()
289                    .map(|x| x.gles3_command_buffer().unwrap())
290                    .collect();
291                let wait_semaphores: Vec<_> = wait_semaphores
292                    .iter()
293                    .map(|x| x.gles3_semaphore().unwrap())
294                    .collect();
295                let signal_semaphores: Vec<_> = signal_semaphores
296                    .iter()
297                    .map(|x| x.gles3_semaphore().unwrap())
298                    .collect();
299                inner.submit(
300                    &command_buffers,
301                    &wait_semaphores,
302                    &signal_semaphores,
303                    signal_fence.map(|x| x.gles3_fence().unwrap()),
304                )
305            }
306            #[cfg(any(
307                feature = "rafx-empty",
308                not(any(
309                    feature = "rafx-dx12",
310                    feature = "rafx-metal",
311                    feature = "rafx-vulkan",
312                    feature = "rafx-gles2",
313                    feature = "rafx-gles3"
314                ))
315            ))]
316            RafxQueue::Empty(inner) => {
317                let command_buffers: Vec<_> = command_buffers
318                    .iter()
319                    .map(|x| x.empty_command_buffer().unwrap())
320                    .collect();
321                let wait_semaphores: Vec<_> = wait_semaphores
322                    .iter()
323                    .map(|x| x.empty_semaphore().unwrap())
324                    .collect();
325                let signal_semaphores: Vec<_> = signal_semaphores
326                    .iter()
327                    .map(|x| x.empty_semaphore().unwrap())
328                    .collect();
329                inner.submit(
330                    &command_buffers,
331                    &wait_semaphores,
332                    &signal_semaphores,
333                    signal_fence.map(|x| x.empty_fence().unwrap()),
334                )
335            }
336        }
337    }
338
339    /// Presents an image in the swapchain.
340    ///
341    /// Execution will not begin until all `wait_semaphores` are signaled.
342    pub fn present(
343        &self,
344        swapchain: &RafxSwapchain,
345        wait_semaphores: &[&RafxSemaphore],
346        image_index: u32,
347    ) -> RafxResult<RafxPresentSuccessResult> {
348        match self {
349            #[cfg(feature = "rafx-dx12")]
350            RafxQueue::Dx12(inner) => {
351                let wait_semaphores: Vec<_> = wait_semaphores
352                    .iter()
353                    .map(|x| x.dx12_semaphore().unwrap())
354                    .collect();
355                inner.present(
356                    swapchain.dx12_swapchain().unwrap(),
357                    &wait_semaphores,
358                    image_index,
359                )
360            }
361            #[cfg(feature = "rafx-vulkan")]
362            RafxQueue::Vk(inner) => {
363                let wait_semaphores: Vec<_> = wait_semaphores
364                    .iter()
365                    .map(|x| x.vk_semaphore().unwrap())
366                    .collect();
367                inner.present(
368                    swapchain.vk_swapchain().unwrap(),
369                    &wait_semaphores,
370                    image_index,
371                )
372            }
373            #[cfg(feature = "rafx-metal")]
374            RafxQueue::Metal(inner) => {
375                let wait_semaphores: Vec<_> = wait_semaphores
376                    .iter()
377                    .map(|x| x.metal_semaphore().unwrap())
378                    .collect();
379                inner.present(
380                    swapchain.metal_swapchain().unwrap(),
381                    &wait_semaphores,
382                    image_index,
383                )
384            }
385            #[cfg(feature = "rafx-gles2")]
386            RafxQueue::Gles2(inner) => {
387                let wait_semaphores: Vec<_> = wait_semaphores
388                    .iter()
389                    .map(|x| x.gles2_semaphore().unwrap())
390                    .collect();
391                inner.present(
392                    swapchain.gles2_swapchain().unwrap(),
393                    &wait_semaphores,
394                    image_index,
395                )
396            }
397            #[cfg(feature = "rafx-gles3")]
398            RafxQueue::Gles3(inner) => {
399                let wait_semaphores: Vec<_> = wait_semaphores
400                    .iter()
401                    .map(|x| x.gles3_semaphore().unwrap())
402                    .collect();
403                inner.present(
404                    swapchain.gles3_swapchain().unwrap(),
405                    &wait_semaphores,
406                    image_index,
407                )
408            }
409            #[cfg(any(
410                feature = "rafx-empty",
411                not(any(
412                    feature = "rafx-dx12",
413                    feature = "rafx-metal",
414                    feature = "rafx-vulkan",
415                    feature = "rafx-gles2",
416                    feature = "rafx-gles3"
417                ))
418            ))]
419            RafxQueue::Empty(inner) => {
420                let wait_semaphores: Vec<_> = wait_semaphores
421                    .iter()
422                    .map(|x| x.empty_semaphore().unwrap())
423                    .collect();
424                inner.present(
425                    swapchain.empty_swapchain().unwrap(),
426                    &wait_semaphores,
427                    image_index,
428                )
429            }
430        }
431    }
432
433    /// Wait until all work submitted to this queue is completed
434    pub fn wait_for_queue_idle(&self) -> RafxResult<()> {
435        match self {
436            #[cfg(feature = "rafx-dx12")]
437            RafxQueue::Dx12(inner) => inner.wait_for_queue_idle(),
438            #[cfg(feature = "rafx-vulkan")]
439            RafxQueue::Vk(inner) => inner.wait_for_queue_idle(),
440            #[cfg(feature = "rafx-metal")]
441            RafxQueue::Metal(inner) => inner.wait_for_queue_idle(),
442            #[cfg(feature = "rafx-gles2")]
443            RafxQueue::Gles2(inner) => inner.wait_for_queue_idle(),
444            #[cfg(feature = "rafx-gles3")]
445            RafxQueue::Gles3(inner) => inner.wait_for_queue_idle(),
446            #[cfg(any(
447                feature = "rafx-empty",
448                not(any(
449                    feature = "rafx-dx12",
450                    feature = "rafx-metal",
451                    feature = "rafx-vulkan",
452                    feature = "rafx-gles2",
453                    feature = "rafx-gles3"
454                ))
455            ))]
456            RafxQueue::Empty(inner) => inner.wait_for_queue_idle(),
457        }
458    }
459
460    /// Get the underlying vulkan API object. This provides access to any internally created
461    /// vulkan objects.
462    #[cfg(feature = "rafx-dx12")]
463    pub fn dx12_queue(&self) -> Option<&RafxQueueDx12> {
464        match self {
465            #[cfg(feature = "rafx-dx12")]
466            RafxQueue::Dx12(inner) => Some(inner),
467            #[cfg(feature = "rafx-vulkan")]
468            RafxQueue::Vk(_) => None,
469            #[cfg(feature = "rafx-metal")]
470            RafxQueue::Metal(_) => None,
471            #[cfg(feature = "rafx-gles2")]
472            RafxQueue::Gles2(_) => None,
473            #[cfg(feature = "rafx-gles3")]
474            RafxQueue::Gles3(_) => None,
475            #[cfg(any(
476                feature = "rafx-empty",
477                not(any(
478                    feature = "rafx-dx12",
479                    feature = "rafx-metal",
480                    feature = "rafx-vulkan",
481                    feature = "rafx-gles2",
482                    feature = "rafx-gles3"
483                ))
484            ))]
485            RafxQueue::Empty(_) => None,
486        }
487    }
488
489    /// Get the underlying vulkan API object. This provides access to any internally created
490    /// vulkan objects.
491    #[cfg(feature = "rafx-vulkan")]
492    pub fn vk_queue(&self) -> Option<&RafxQueueVulkan> {
493        match self {
494            #[cfg(feature = "rafx-dx12")]
495            RafxQueue::Dx12(_) => None,
496            #[cfg(feature = "rafx-vulkan")]
497            RafxQueue::Vk(inner) => Some(inner),
498            #[cfg(feature = "rafx-metal")]
499            RafxQueue::Metal(_) => None,
500            #[cfg(feature = "rafx-gles2")]
501            RafxQueue::Gles2(_) => None,
502            #[cfg(feature = "rafx-gles3")]
503            RafxQueue::Gles3(_) => None,
504            #[cfg(any(
505                feature = "rafx-empty",
506                not(any(
507                    feature = "rafx-dx12",
508                    feature = "rafx-metal",
509                    feature = "rafx-vulkan",
510                    feature = "rafx-gles2",
511                    feature = "rafx-gles3"
512                ))
513            ))]
514            RafxQueue::Empty(_) => None,
515        }
516    }
517
518    /// Get the underlying metal API object. This provides access to any internally created
519    /// metal objects.
520    #[cfg(feature = "rafx-metal")]
521    pub fn metal_queue(&self) -> Option<&RafxQueueMetal> {
522        match self {
523            #[cfg(feature = "rafx-dx12")]
524            RafxQueue::Dx12(_) => None,
525            #[cfg(feature = "rafx-vulkan")]
526            RafxQueue::Vk(_) => None,
527            #[cfg(feature = "rafx-metal")]
528            RafxQueue::Metal(inner) => Some(inner),
529            #[cfg(feature = "rafx-gles2")]
530            RafxQueue::Gles2(_) => None,
531            #[cfg(feature = "rafx-gles3")]
532            RafxQueue::Gles3(_) => None,
533            #[cfg(any(
534                feature = "rafx-empty",
535                not(any(
536                    feature = "rafx-dx12",
537                    feature = "rafx-metal",
538                    feature = "rafx-vulkan",
539                    feature = "rafx-gles2",
540                    feature = "rafx-gles3"
541                ))
542            ))]
543            RafxQueue::Empty(_) => None,
544        }
545    }
546
547    /// Get the underlying metal API object. This provides access to any internally created
548    /// metal objects.
549    #[cfg(feature = "rafx-gles2")]
550    pub fn gles2_queue(&self) -> Option<&RafxQueueGles2> {
551        match self {
552            #[cfg(feature = "rafx-dx12")]
553            RafxQueue::Dx12(_) => None,
554            #[cfg(feature = "rafx-vulkan")]
555            RafxQueue::Vk(_) => None,
556            #[cfg(feature = "rafx-metal")]
557            RafxQueue::Metal(_) => None,
558            #[cfg(feature = "rafx-gles2")]
559            RafxQueue::Gles2(inner) => Some(inner),
560            #[cfg(feature = "rafx-gles3")]
561            RafxQueue::Gles3(_) => None,
562            #[cfg(any(
563                feature = "rafx-empty",
564                not(any(
565                    feature = "rafx-dx12",
566                    feature = "rafx-metal",
567                    feature = "rafx-vulkan",
568                    feature = "rafx-gles2",
569                    feature = "rafx-gles3"
570                ))
571            ))]
572            RafxQueue::Empty(_) => None,
573        }
574    }
575
576    /// Get the underlying metal API object. This provides access to any internally created
577    /// metal objects.
578    #[cfg(feature = "rafx-gles3")]
579    pub fn gles3_queue(&self) -> Option<&RafxQueueGles3> {
580        match self {
581            #[cfg(feature = "rafx-dx12")]
582            RafxQueue::Dx12(_) => None,
583            #[cfg(feature = "rafx-vulkan")]
584            RafxQueue::Vk(_) => None,
585            #[cfg(feature = "rafx-metal")]
586            RafxQueue::Metal(_) => None,
587            #[cfg(feature = "rafx-gles2")]
588            RafxQueue::Gles2(_) => None,
589            #[cfg(feature = "rafx-gles3")]
590            RafxQueue::Gles3(inner) => Some(inner),
591            #[cfg(any(
592                feature = "rafx-empty",
593                not(any(
594                    feature = "rafx-dx12",
595                    feature = "rafx-metal",
596                    feature = "rafx-vulkan",
597                    feature = "rafx-gles2",
598                    feature = "rafx-gles3"
599                ))
600            ))]
601            RafxQueue::Empty(_) => None,
602        }
603    }
604
605    /// Get the underlying metal API object. This provides access to any internally created
606    /// metal objects.
607    #[cfg(any(
608        feature = "rafx-empty",
609        not(any(
610            feature = "rafx-dx12",
611            feature = "rafx-metal",
612            feature = "rafx-vulkan",
613            feature = "rafx-gles2",
614            feature = "rafx-gles3"
615        ))
616    ))]
617    pub fn empty_queue(&self) -> Option<&RafxQueueEmpty> {
618        match self {
619            #[cfg(feature = "rafx-dx12")]
620            RafxQueue::Dx12(_) => None,
621            #[cfg(feature = "rafx-vulkan")]
622            RafxQueue::Vk(_) => None,
623            #[cfg(feature = "rafx-metal")]
624            RafxQueue::Metal(_) => None,
625            #[cfg(feature = "rafx-gles2")]
626            RafxQueue::Gles2(_) => None,
627            #[cfg(feature = "rafx-gles3")]
628            RafxQueue::Gles3(_) => None,
629            #[cfg(any(
630                feature = "rafx-empty",
631                not(any(
632                    feature = "rafx-dx12",
633                    feature = "rafx-metal",
634                    feature = "rafx-vulkan",
635                    feature = "rafx-gles2",
636                    feature = "rafx-gles3"
637                ))
638            ))]
639            RafxQueue::Empty(inner) => Some(inner),
640        }
641    }
642}