From 799c6aa62915c832e7b35b98b39d9bd4a9f018a0 Mon Sep 17 00:00:00 2001
From: Ethan Lee <[EMAIL REDACTED]>
Date: Thu, 6 Nov 2025 20:57:26 -0500
Subject: [PATCH] gpu: Move device ranking to a standalone function.
This allows us to treat Dozen as an "other" driver, rather than blacklisting it outright.
---
src/gpu/vulkan/SDL_gpu_vulkan.c | 173 +++++++++++++++++---------------
1 file changed, 94 insertions(+), 79 deletions(-)
diff --git a/src/gpu/vulkan/SDL_gpu_vulkan.c b/src/gpu/vulkan/SDL_gpu_vulkan.c
index 4dd794e9388a4..5f749de3b3434 100644
--- a/src/gpu/vulkan/SDL_gpu_vulkan.c
+++ b/src/gpu/vulkan/SDL_gpu_vulkan.c
@@ -81,22 +81,6 @@ typedef struct VulkanExtensions
// Conversions
-static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
- 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
- 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
- 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
- 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
- 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
-};
-
-static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
- 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
- 4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
- 3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
- 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
- 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
-};
-
static VkPresentModeKHR SDLToVK_PresentMode[] = {
VK_PRESENT_MODE_FIFO_KHR,
VK_PRESENT_MODE_IMMEDIATE_KHR,
@@ -11307,35 +11291,62 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
return 1;
}
-static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
+static bool VULKAN_INTERNAL_GetDeviceRank(
VulkanRenderer *renderer,
VkPhysicalDevice physicalDevice,
VulkanExtensions *physicalDeviceExtensions,
- Uint32 *queueFamilyIndex,
Uint64 *deviceRank)
{
- Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
- VkQueueFamilyProperties *queueProps;
- bool supportsPresent;
- VkPhysicalDeviceProperties deviceProperties;
- VkPhysicalDeviceFeatures deviceFeatures;
- VkPhysicalDeviceMemoryProperties deviceMemory;
- Uint32 i;
-
+ static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
+ 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
+ 3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
+ 4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
+ 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
+ 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
+ };
+ static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
+ 0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
+ 4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
+ 3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
+ 2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
+ 1 // VK_PHYSICAL_DEVICE_TYPE_CPU
+ };
const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
- /* Get the device rank before doing any checks, in case one fails.
- * Note: If no dedicated device exists, one that supports our features
- * would be fine
- */
- renderer->vkGetPhysicalDeviceProperties(
- physicalDevice,
- &deviceProperties);
+ VkPhysicalDeviceType deviceType;
+ if (physicalDeviceExtensions->MSFT_layered_driver) {
+ VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
+ VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
+
+ physicalDeviceProperties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
+ physicalDeviceProperties.pNext = &physicalDeviceLayeredDriverProperties;
+
+ physicalDeviceLayeredDriverProperties.sType =
+ VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
+ physicalDeviceLayeredDriverProperties.pNext = NULL;
+
+ renderer->vkGetPhysicalDeviceProperties2KHR(
+ physicalDevice,
+ &physicalDeviceProperties);
+
+ if (physicalDeviceLayeredDriverProperties.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
+ deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
+ } else {
+ deviceType = physicalDeviceProperties.properties.deviceType;
+ }
+ } else {
+ VkPhysicalDeviceProperties physicalDeviceProperties;
+ renderer->vkGetPhysicalDeviceProperties(
+ physicalDevice,
+ &physicalDeviceProperties);
+ deviceType = physicalDeviceProperties.deviceType;
+ }
/* Apply a large bias on the devicePriority so that we always respect the order in the priority arrays.
* We also rank by e.g. VRAM which should have less influence than the device type.
*/
- Uint64 devicePriorityValue = devicePriority[deviceProperties.deviceType] * 1000000;
+ Uint64 devicePriorityValue = devicePriority[deviceType] * 1000000;
if (*deviceRank < devicePriorityValue) {
/* This device outranks the best device we've found so far!
@@ -11349,9 +11360,50 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
* run a query and reset the rank to avoid overwrites
*/
*deviceRank = 0;
- return 0;
+ return false;
}
+ /* If we prefer high performance, sum up all device local memory (rounded to megabytes)
+ * to deviceRank. In the niche case of someone having multiple dedicated GPUs in the same
+ * system, this theoretically picks the most powerful one (or at least the one with the
+ * most memory!)
+ *
+ * We do this *after* discarding all non suitable devices, which means if this computer
+ * has multiple dedicated GPUs that all meet our criteria, *and* the user asked for high
+ * performance, then we always pick the GPU with more VRAM.
+ */
+ if (!renderer->preferLowPower) {
+ Uint32 i;
+ Uint64 videoMemory = 0;
+ VkPhysicalDeviceMemoryProperties deviceMemory;
+ renderer->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemory);
+ for (i = 0; i < deviceMemory.memoryHeapCount; i++) {
+ VkMemoryHeap heap = deviceMemory.memoryHeaps[i];
+ if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
+ videoMemory += heap.size;
+ }
+ }
+ // Round it to megabytes (as per the vulkan spec videoMemory is in bytes)
+ Uint64 videoMemoryRounded = videoMemory / 1024 / 1024;
+ *deviceRank += videoMemoryRounded;
+ }
+
+ return true;
+}
+
+static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
+ VulkanRenderer *renderer,
+ VkPhysicalDevice physicalDevice,
+ VulkanExtensions *physicalDeviceExtensions,
+ Uint32 *queueFamilyIndex,
+ Uint64 *deviceRank)
+{
+ Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
+ VkQueueFamilyProperties *queueProps;
+ bool supportsPresent;
+ VkPhysicalDeviceFeatures deviceFeatures;
+ Uint32 i;
+
renderer->vkGetPhysicalDeviceFeatures(
physicalDevice,
&deviceFeatures);
@@ -11373,26 +11425,13 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
return 0;
}
- // Ignore Dozen, for now
- if (renderer->supports.MSFT_layered_driver) {
- VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
- VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
-
- physicalDeviceProperties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
- physicalDeviceProperties.pNext = &physicalDeviceLayeredDriverProperties;
-
- physicalDeviceLayeredDriverProperties.sType =
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
- physicalDeviceLayeredDriverProperties.pNext = NULL;
-
- renderer->vkGetPhysicalDeviceProperties2KHR(
- renderer->physicalDevice,
- &physicalDeviceProperties);
-
- if (physicalDeviceLayeredDriverProperties.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
- return 0;
- }
+ // Device rank depends on extension support, do NOT move this block any higher!
+ if (!VULKAN_INTERNAL_GetDeviceRank(
+ renderer,
+ physicalDevice,
+ physicalDeviceExtensions,
+ deviceRank)) {
+ return 0;
}
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
@@ -11469,30 +11508,6 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
return 0;
}
- /* If we prefer high performance, sum up all device local memory (rounded to megabytes)
- * to deviceRank. In the niche case of someone having multiple dedicated GPUs in the same
- * system, this theoretically picks the most powerful one (or at least the one with the
- * most memory!)
- *
- * We do this *after* discarding all non suitable devices, which means if this computer
- * has multiple dedicated GPUs that all meet our criteria, *and* the user asked for high
- * performance, then we always pick the GPU with more VRAM.
- */
- if (!renderer->preferLowPower) {
- renderer->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemory);
- Uint64 videoMemory = 0;
- for (i = 0; i < deviceMemory.memoryHeapCount; i++) {
- VkMemoryHeap heap = deviceMemory.memoryHeaps[i];
- if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
- videoMemory += heap.size;
- }
- }
- // Round it to megabytes (as per the vulkan spec videoMemory is in bytes)
- Uint64 videoMemoryRounded = videoMemory / 1024 / 1024;
- *deviceRank += videoMemoryRounded;
- }
-
-
// FIXME: Need better structure for checking vs storing swapchain support details
return 1;
}