1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
use crate::graphics::vulkan::WindowSurface;
use super::Queue;
use anyhow::{Context, Result};
use ash::{
version::{DeviceV1_0, InstanceV1_0},
vk,
};
pub struct QueueFamilyIndices {
graphics_family_index: u32,
present_family_index: u32,
}
impl QueueFamilyIndices {
pub fn find(
physical_device: &vk::PhysicalDevice,
ash: &ash::Instance,
window_surface: &dyn WindowSurface,
) -> Result<Self> {
let queue_families = unsafe {
ash.get_physical_device_queue_family_properties(*physical_device)
};
let mut graphics_family = None;
let mut present_family = None;
queue_families.iter().enumerate().for_each(|(i, family)| {
if family.queue_flags.contains(vk::QueueFlags::GRAPHICS) {
graphics_family = Some(i as u32);
}
let present_support = unsafe {
window_surface.get_physical_device_surface_support(
physical_device,
i as u32,
)
};
match present_support {
Ok(true) => {
present_family = Some(i as u32);
}
_ => {}
}
});
let graphics_family_index = graphics_family
.context("unable to find queue family which supports graphics")?;
let present_family_index = present_family
.context("unable to find a queue which supports presentation")?;
Ok(Self {
graphics_family_index,
present_family_index,
})
}
const SINGLE_QUEUE_PRIORITY: [f32; 1] = [1.0];
pub fn as_queue_create_infos(&self) -> Vec<vk::DeviceQueueCreateInfo> {
let mut create_infos = vec![vk::DeviceQueueCreateInfo {
queue_family_index: self.graphics_family_index,
p_queue_priorities: Self::SINGLE_QUEUE_PRIORITY.as_ptr(),
queue_count: 1,
..Default::default()
}];
if self.graphics_family_index != self.present_family_index {
create_infos.push(vk::DeviceQueueCreateInfo {
queue_family_index: self.present_family_index,
p_queue_priorities: Self::SINGLE_QUEUE_PRIORITY.as_ptr(),
queue_count: 1,
..Default::default()
});
}
create_infos
}
pub fn get_queues(
&self,
logical_device: &ash::Device,
) -> Result<(Queue, Queue)> {
let raw_graphics_queue = unsafe {
logical_device.get_device_queue(self.graphics_family_index, 0)
};
let graphics_queue =
Queue::from_raw(raw_graphics_queue, self.graphics_family_index, 0);
let is_same = self.graphics_family_index == self.present_family_index;
let present_queue = if is_same {
graphics_queue
} else {
let raw_present_queue = unsafe {
logical_device.get_device_queue(self.present_family_index, 0)
};
Queue::from_raw(raw_present_queue, self.present_family_index, 0)
};
Ok((graphics_queue, present_queue))
}
}