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
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
mod physical_device_features;
mod physical_device_properties;
use {
crate::{ffi, InstanceResult, VulkanHandle, VulkanInstance},
ash::vk,
indoc::indoc,
};
pub use self::{
physical_device_features::PhysicalDeviceFeatures,
physical_device_properties::PhysicalDeviceProperties,
};
#[derive(Clone)]
pub struct PhysicalDevice {
properties: PhysicalDeviceProperties,
features: PhysicalDeviceFeatures,
available_extensions: Vec<vk::ExtensionProperties>,
available_extension_names: Vec<String>,
queue_family_properties: Vec<vk::QueueFamilyProperties>,
physical_device: vk::PhysicalDevice,
}
impl PhysicalDevice {
pub fn queue_family_properties(&self) -> &[vk::QueueFamilyProperties] {
&self.queue_family_properties
}
pub fn available_extensions(&self) -> &[vk::ExtensionProperties] {
&self.available_extensions
}
pub fn available_extension_names(&self) -> &[String] {
&self.available_extension_names
}
pub fn properties(&self) -> &PhysicalDeviceProperties {
&self.properties
}
pub fn features(&self) -> &PhysicalDeviceFeatures {
&self.features
}
pub fn name(&self) -> String {
ffi::string_from_i8(&self.properties().properties().device_name)
.unwrap()
}
pub fn enumerate_supported_devices(
instance: &VulkanInstance,
required_features: &PhysicalDeviceFeatures,
) -> InstanceResult<Vec<Self>> {
let all_supported_devices: Vec<vk::PhysicalDevice> =
unsafe { instance.ash().enumerate_physical_devices()? }
.into_iter()
.filter(|physical_device| {
required_features.is_supported_by(
&PhysicalDeviceFeatures::from_physical_device(
instance,
physical_device,
),
)
})
.collect();
let mut devices_with_requested_features = vec![];
for physical_device in all_supported_devices {
let properties = PhysicalDeviceProperties::from_physical_device(
instance,
&physical_device,
);
let extension_properties = unsafe {
instance
.ash()
.enumerate_device_extension_properties(physical_device)?
};
let extension_names: Vec<String> = extension_properties
.iter()
.map(|props| ffi::string_from_i8(&props.extension_name))
.filter_map(|name| name.ok())
.collect();
let queue_family_properties = unsafe {
instance.ash().get_physical_device_queue_family_properties(
physical_device,
)
};
devices_with_requested_features.push(Self {
properties,
features: *required_features,
available_extensions: extension_properties,
available_extension_names: extension_names,
queue_family_properties,
physical_device,
});
}
Ok(devices_with_requested_features)
}
}
impl std::fmt::Debug for PhysicalDevice {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if formatter.alternate() {
formatter
.debug_struct("PhysicalDevice")
.field("properties", &self.properties)
.field("features", &self.features)
.field("available_extensions", &self.available_extensions)
.field("queue_family_properties", &self.queue_family_properties)
.finish()
} else {
formatter.write_str(&self.name())
}
}
}
impl std::fmt::Display for PhysicalDevice {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_fmt(format_args!(indoc!("{:?}"), self.name(),))?;
Ok(())
}
}
impl VulkanHandle for PhysicalDevice {
type Handle = vk::PhysicalDevice;
unsafe fn raw(&self) -> &Self::Handle {
&self.physical_device
}
}