1
2use crate::prelude::*;
3use std::{
4 ffi::CStr,
5 fmt::{self, Debug, Formatter},
6 mem::MaybeUninit,
7 ptr::{null, null_mut},
8 sync::Arc,
9};
10
11#[derive(Debug, Clone)]
13pub struct VulkanGpuInfo {
14 pub(crate) gpu: VkPhysicalDevice,
16
17 pub(crate) properties: VkPhysicalDeviceProperties,
19
20 pub(crate) mem_properties: VkPhysicalDeviceMemoryProperties,
22
23 pub(crate) queue_families: Vec<VkQueueFamilyProperties>,
25
26 pub(crate) extension_properties: Vec<VkExtensionProperties>,
28}
29
30impl VulkanGpuInfo {
31 pub fn get_gpu_info(vkcore: &VkCore) -> Result<Vec<VulkanGpuInfo>, VulkanError> {
33 let mut num_gpus = 0u32;
34 vkcore.vkEnumeratePhysicalDevices(vkcore.get_instance(), &mut num_gpus, null_mut())?;
35 let mut gpus = Vec::<VkPhysicalDevice>::with_capacity(num_gpus as usize);
36 vkcore.vkEnumeratePhysicalDevices(vkcore.get_instance(), &mut num_gpus, gpus.as_mut_ptr())?;
37 unsafe {gpus.set_len(num_gpus as usize)};
38 let mut ret = Vec::<VulkanGpuInfo>::with_capacity(num_gpus as usize);
39 for gpu in gpus {
40 let mut properties: VkPhysicalDeviceProperties = unsafe {MaybeUninit::zeroed().assume_init()};
41 vkcore.vkGetPhysicalDeviceProperties(gpu, &mut properties)?;
42 let mut mem_properties: VkPhysicalDeviceMemoryProperties = unsafe {MaybeUninit::zeroed().assume_init()};
43 vkcore.vkGetPhysicalDeviceMemoryProperties(gpu, &mut mem_properties)?;
44 let mut num_queue_families = 0u32;
45 vkcore.vkGetPhysicalDeviceQueueFamilyProperties(gpu, &mut num_queue_families, null_mut())?;
46 let mut queue_families = Vec::<VkQueueFamilyProperties>::with_capacity(num_queue_families as usize);
47 vkcore.vkGetPhysicalDeviceQueueFamilyProperties(gpu, &mut num_queue_families, queue_families.as_mut_ptr())?;
48 unsafe {queue_families.set_len(num_queue_families as usize)};
49 let mut num_extension_properties = 0u32;
50 vkcore.vkEnumerateDeviceExtensionProperties(gpu, null(), &mut num_extension_properties, null_mut())?;
51 let mut extension_properties = Vec::<VkExtensionProperties>::with_capacity(num_extension_properties as usize);
52 vkcore.vkEnumerateDeviceExtensionProperties(gpu, null(), &mut num_extension_properties, extension_properties.as_mut_ptr())?;
53 unsafe {extension_properties.set_len(num_extension_properties as usize)};
54 ret.push(VulkanGpuInfo {
55 gpu,
56 properties,
57 mem_properties,
58 queue_families,
59 extension_properties,
60 });
61 }
62 Ok(ret)
63 }
64
65 pub(crate) fn get_vk_physical_device(&self) -> VkPhysicalDevice {
67 self.gpu
68 }
69
70 pub fn get_queue_families(&self) -> &[VkQueueFamilyProperties] {
72 self.queue_families.as_ref()
73 }
74
75 pub fn get_queue_family_index_by_flags(&self, queue_flag_match: u32) -> u32 {
77 for i in 0..self.queue_families.len() {
78 if (self.queue_families[i].queueFlags & queue_flag_match) == queue_flag_match {
79 return i as u32;
80 }
81 }
82 u32::MAX
83 }
84
85 pub fn get_properties(&self) -> &VkPhysicalDeviceProperties {
87 &self.properties
88 }
89
90 pub fn get_extension_properties(&self) -> &[VkExtensionProperties] {
92 self.extension_properties.as_ref()
93 }
94
95 pub fn get_memory_type_index(&self, mut type_bits: u32, properties: VkMemoryPropertyFlags) -> Result<u32, VulkanError> {
97 for i in 0..self.mem_properties.memoryTypeCount {
98 if (type_bits & 1) == 1
99 && (self.mem_properties.memoryTypes[i as usize].propertyFlags & properties) == properties {
100 return Ok(i)
101 }
102 type_bits >>= 1;
103 }
104 Err(VulkanError::NoSuitableMemoryType)
105 }
106}
107
108unsafe impl Send for VulkanGpuInfo {}
109unsafe impl Sync for VulkanGpuInfo {}
110
111pub struct VulkanDevice {
113 pub(crate) vkcore: Arc<VkCore>,
115
116 queue_family_index: u32,
118
119 gpu: VulkanGpuInfo,
121
122 device: VkDevice,
124
125 pub(crate) queue: VkQueue,
127}
128
129impl VulkanDevice {
130 pub fn new(vkcore: Arc<VkCore>, gpu: VulkanGpuInfo, queue_family_index: u32) -> Result<Self, VulkanError> {
132 let priorities = [1.0_f32];
133 let queue_ci = VkDeviceQueueCreateInfo {
134 sType: VkStructureType::VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
135 pNext: null(),
136 flags: 0,
137 queueFamilyIndex: queue_family_index,
138 queueCount: 1,
139 pQueuePriorities: priorities.as_ptr(),
140 };
141 let mut extensions: Vec<*const i8> = Vec::with_capacity(gpu.extension_properties.len());
142 let mut has_vk_khr_buffer_device_address = false;
143 let mut has_vk_ext_buffer_device_address = false;
144 for ext in gpu.extension_properties.iter() {
145 let ext_ptr = ext.extensionName.as_ptr();
146 let ext_str = unsafe {CStr::from_ptr(ext_ptr)}.to_string_lossy();
147 if ext_str == "VK_KHR_buffer_device_address" {
148 has_vk_khr_buffer_device_address = true;
149 } else if ext_str == "VK_EXT_buffer_device_address" {
150 has_vk_ext_buffer_device_address = true;
151 }
152 extensions.push(ext_ptr)
153 }
154 if has_vk_khr_buffer_device_address && has_vk_ext_buffer_device_address {
155 let len = extensions.len();
156 for i in 0..len {
157 let ext_ptr = extensions[i];
158 let ext_str = unsafe {CStr::from_ptr(ext_ptr)}.to_string_lossy();
159 if ext_str == "VK_EXT_buffer_device_address" {
160 extensions[i] = extensions[len - 1];
161 extensions.pop();
162 break;
163 }
164 }
165 }
166
167 let device_ci = VkDeviceCreateInfo {
168 sType: VkStructureType::VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
169 pNext: null(),
170 flags: 0,
171 queueCreateInfoCount: 1,
172 pQueueCreateInfos: &queue_ci,
173 enabledLayerCount: 0,
174 ppEnabledLayerNames: null(),
175 enabledExtensionCount: extensions.len() as u32,
176 ppEnabledExtensionNames: extensions.as_ptr(),
177 pEnabledFeatures: null(),
178 };
179
180 let mut device: VkDevice = null();
181 vkcore.vkCreateDevice(gpu.get_vk_physical_device(), &device_ci, null(), &mut device)?;
182 let device = ResourceGuard::new(device, |&d|proceed_run(vkcore.vkDestroyDevice(d, null())));
183
184 let mut queue: VkQueue = null();
185 vkcore.vkGetDeviceQueue(*device, queue_family_index, 0, &mut queue)?;
186 let device = device.release();
187
188 Ok(Self {
189 vkcore,
190 queue_family_index,
191 gpu,
192 device,
193 queue,
194 })
195 }
196
197 pub fn choose_gpu(vkcore: Arc<VkCore>, flags: VkQueueFlags) -> Result<Self, VulkanError> {
201 for gpu in VulkanGpuInfo::get_gpu_info(&vkcore)?.iter() {
202 let index = gpu.get_queue_family_index_by_flags(flags);
203 if index != u32::MAX {
204 return Self::new(vkcore, gpu.clone(), index);
205 }
206 }
207 Err(VulkanError::ChooseGpuFailed)
208 }
209
210 pub fn choose_gpu_with_graphics(vkcore: Arc<VkCore>) -> Result<Self, VulkanError> {
213 Self::choose_gpu(vkcore, VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT as VkQueueFlags)
214 }
215
216 pub fn choose_gpu_with_compute(vkcore: Arc<VkCore>) -> Result<Self, VulkanError> {
219 Self::choose_gpu(vkcore, VkQueueFlagBits::VK_QUEUE_COMPUTE_BIT as VkQueueFlags)
220 }
221
222 pub fn choose_gpu_with_graphics_and_compute(vkcore: Arc<VkCore>) -> Result<Self, VulkanError> {
225 Self::choose_gpu(vkcore,
226 VkQueueFlagBits::VK_QUEUE_GRAPHICS_BIT as VkQueueFlags |
227 VkQueueFlagBits::VK_QUEUE_COMPUTE_BIT as VkQueueFlags)
228 }
229
230 pub fn choose_gpu_anyway(vkcore: Arc<VkCore>) -> Result<Self, VulkanError> {
233 Self::choose_gpu(vkcore, 0)
234 }
235
236 pub fn get_queue_family_index(&self) -> u32 {
238 self.queue_family_index
239 }
240
241 pub fn get_gpu(&self) -> &VulkanGpuInfo {
243 &self.gpu
244 }
245
246 pub fn get_supported_by_surface(&self, queue_index: usize, surface: VkSurfaceKHR) -> Result<bool, VulkanError> {
248 let mut result: VkBool32 = 0;
249 self.vkcore.vkGetPhysicalDeviceSurfaceSupportKHR(self.get_vk_physical_device(), queue_index as u32, surface, &mut result)?;
250 Ok(result != 0)
251 }
252
253 pub fn wait_idle(&self) -> Result<(), VulkanError> {
255 self.vkcore.vkDeviceWaitIdle(self.device)?;
256 Ok(())
257 }
258
259 pub(crate) fn get_vk_physical_device(&self) -> VkPhysicalDevice {
261 self.gpu.get_vk_physical_device()
262 }
263
264 pub(crate) fn get_vk_device(&self) -> VkDevice {
266 self.device
267 }
268
269 pub(crate) fn get_vk_queue(&self) -> VkQueue {
271 self.queue
272 }
273}
274
275impl Debug for VulkanDevice {
276 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
277 f.debug_struct("VulkanDevice")
278 .field("queue_family_index", &self.queue_family_index)
279 .field("gpu", &self.gpu)
280 .field("device", &self.device)
281 .field("queue", &self.queue)
282 .finish()
283 }
284}
285
286impl Clone for VulkanDevice {
287 fn clone(&self) -> Self {
288 Self::new(self.vkcore.clone(), self.gpu.clone(), self.queue_family_index).unwrap()
289 }
290}
291
292impl Drop for VulkanDevice {
293 fn drop(&mut self) {
294 proceed_run(self.vkcore.vkDestroyDevice(self.device, null()))
295 }
296}
297
298unsafe impl Send for VulkanDevice {}
299unsafe impl Sync for VulkanDevice {}