Skip to content

Commit 0b15ff3

Browse files
committed
gpu: Move device ranking to a standalone function.
This allows us to treat Dozen as an "other" driver, rather than blacklisting it outright.
1 parent 521c5ed commit 0b15ff3

File tree

1 file changed

+90
-80
lines changed

1 file changed

+90
-80
lines changed

src/gpu/vulkan/SDL_gpu_vulkan.c

Lines changed: 90 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,6 @@ typedef struct VulkanExtensions
8181

8282
// Conversions
8383

84-
static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
85-
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
86-
3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
87-
4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
88-
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
89-
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
90-
};
91-
92-
static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
93-
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
94-
4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
95-
3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
96-
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
97-
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
98-
};
99-
10084
static VkPresentModeKHR SDLToVK_PresentMode[] = {
10185
VK_PRESENT_MODE_FIFO_KHR,
10286
VK_PRESENT_MODE_IMMEDIATE_KHR,
@@ -11307,35 +11291,61 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
1130711291
return 1;
1130811292
}
1130911293

11310-
static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
11294+
static bool VULKAN_INTERNAL_GetDeviceRank(
1131111295
VulkanRenderer *renderer,
1131211296
VkPhysicalDevice physicalDevice,
11313-
VulkanExtensions *physicalDeviceExtensions,
11314-
Uint32 *queueFamilyIndex,
1131511297
Uint64 *deviceRank)
1131611298
{
11317-
Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
11318-
VkQueueFamilyProperties *queueProps;
11319-
bool supportsPresent;
11320-
VkPhysicalDeviceProperties deviceProperties;
11321-
VkPhysicalDeviceFeatures deviceFeatures;
11322-
VkPhysicalDeviceMemoryProperties deviceMemory;
11323-
Uint32 i;
11324-
11299+
static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
11300+
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
11301+
3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
11302+
4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
11303+
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
11304+
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
11305+
};
11306+
static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
11307+
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
11308+
4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
11309+
3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
11310+
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
11311+
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
11312+
};
1132511313
const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
1132611314

11327-
/* Get the device rank before doing any checks, in case one fails.
11328-
* Note: If no dedicated device exists, one that supports our features
11329-
* would be fine
11330-
*/
11331-
renderer->vkGetPhysicalDeviceProperties(
11332-
physicalDevice,
11333-
&deviceProperties);
11315+
VkPhysicalDeviceType deviceType;
11316+
if (renderer->supports.MSFT_layered_driver) {
11317+
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
11318+
VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
11319+
11320+
physicalDeviceProperties.sType =
11321+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
11322+
physicalDeviceProperties.pNext = &physicalDeviceLayeredDriverProperties;
11323+
11324+
physicalDeviceLayeredDriverProperties.sType =
11325+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
11326+
physicalDeviceLayeredDriverProperties.pNext = NULL;
11327+
11328+
renderer->vkGetPhysicalDeviceProperties2KHR(
11329+
physicalDevice,
11330+
&physicalDeviceProperties);
11331+
11332+
if (physicalDeviceLayeredDriverProperties.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
11333+
deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
11334+
} else {
11335+
deviceType = physicalDeviceProperties.properties.deviceType;
11336+
}
11337+
} else {
11338+
VkPhysicalDeviceProperties physicalDeviceProperties;
11339+
renderer->vkGetPhysicalDeviceProperties(
11340+
physicalDevice,
11341+
&physicalDeviceProperties);
11342+
deviceType = physicalDeviceProperties.deviceType;
11343+
}
1133411344

1133511345
/* Apply a large bias on the devicePriority so that we always respect the order in the priority arrays.
1133611346
* We also rank by e.g. VRAM which should have less influence than the device type.
1133711347
*/
11338-
Uint64 devicePriorityValue = devicePriority[deviceProperties.deviceType] * 1000000;
11348+
Uint64 devicePriorityValue = devicePriority[deviceType] * 1000000;
1133911349

1134011350
if (*deviceRank < devicePriorityValue) {
1134111351
/* This device outranks the best device we've found so far!
@@ -11349,9 +11359,50 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1134911359
* run a query and reset the rank to avoid overwrites
1135011360
*/
1135111361
*deviceRank = 0;
11352-
return 0;
11362+
return false;
11363+
}
11364+
11365+
/* If we prefer high performance, sum up all device local memory (rounded to megabytes)
11366+
* to deviceRank. In the niche case of someone having multiple dedicated GPUs in the same
11367+
* system, this theoretically picks the most powerful one (or at least the one with the
11368+
* most memory!)
11369+
*
11370+
* We do this *after* discarding all non suitable devices, which means if this computer
11371+
* has multiple dedicated GPUs that all meet our criteria, *and* the user asked for high
11372+
* performance, then we always pick the GPU with more VRAM.
11373+
*/
11374+
if (!renderer->preferLowPower) {
11375+
Uint32 i;
11376+
Uint64 videoMemory = 0;
11377+
VkPhysicalDeviceMemoryProperties deviceMemory;
11378+
renderer->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemory);
11379+
for (i = 0; i < deviceMemory.memoryHeapCount; i++) {
11380+
VkMemoryHeap heap = deviceMemory.memoryHeaps[i];
11381+
if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
11382+
videoMemory += heap.size;
11383+
}
11384+
}
11385+
// Round it to megabytes (as per the vulkan spec videoMemory is in bytes)
11386+
Uint64 videoMemoryRounded = videoMemory / 1024 / 1024;
11387+
*deviceRank += videoMemoryRounded;
1135311388
}
1135411389

11390+
return true;
11391+
}
11392+
11393+
static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
11394+
VulkanRenderer *renderer,
11395+
VkPhysicalDevice physicalDevice,
11396+
VulkanExtensions *physicalDeviceExtensions,
11397+
Uint32 *queueFamilyIndex,
11398+
Uint64 *deviceRank)
11399+
{
11400+
Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
11401+
VkQueueFamilyProperties *queueProps;
11402+
bool supportsPresent;
11403+
VkPhysicalDeviceFeatures deviceFeatures;
11404+
Uint32 i;
11405+
1135511406
renderer->vkGetPhysicalDeviceFeatures(
1135611407
physicalDevice,
1135711408
&deviceFeatures);
@@ -11373,26 +11424,9 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1137311424
return 0;
1137411425
}
1137511426

11376-
// Ignore Dozen, for now
11377-
if (renderer->supports.MSFT_layered_driver) {
11378-
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
11379-
VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
11380-
11381-
physicalDeviceProperties.sType =
11382-
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
11383-
physicalDeviceProperties.pNext = &physicalDeviceLayeredDriverProperties;
11384-
11385-
physicalDeviceLayeredDriverProperties.sType =
11386-
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
11387-
physicalDeviceLayeredDriverProperties.pNext = NULL;
11388-
11389-
renderer->vkGetPhysicalDeviceProperties2KHR(
11390-
renderer->physicalDevice,
11391-
&physicalDeviceProperties);
11392-
11393-
if (physicalDeviceLayeredDriverProperties.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
11394-
return 0;
11395-
}
11427+
// Device rank depends on extension support, do NOT move this block any higher!
11428+
if (!VULKAN_INTERNAL_GetDeviceRank(renderer, physicalDevice, deviceRank)) {
11429+
return 0;
1139611430
}
1139711431

1139811432
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
@@ -11469,30 +11503,6 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1146911503
return 0;
1147011504
}
1147111505

11472-
/* If we prefer high performance, sum up all device local memory (rounded to megabytes)
11473-
* to deviceRank. In the niche case of someone having multiple dedicated GPUs in the same
11474-
* system, this theoretically picks the most powerful one (or at least the one with the
11475-
* most memory!)
11476-
*
11477-
* We do this *after* discarding all non suitable devices, which means if this computer
11478-
* has multiple dedicated GPUs that all meet our criteria, *and* the user asked for high
11479-
* performance, then we always pick the GPU with more VRAM.
11480-
*/
11481-
if (!renderer->preferLowPower) {
11482-
renderer->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemory);
11483-
Uint64 videoMemory = 0;
11484-
for (i = 0; i < deviceMemory.memoryHeapCount; i++) {
11485-
VkMemoryHeap heap = deviceMemory.memoryHeaps[i];
11486-
if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
11487-
videoMemory += heap.size;
11488-
}
11489-
}
11490-
// Round it to megabytes (as per the vulkan spec videoMemory is in bytes)
11491-
Uint64 videoMemoryRounded = videoMemory / 1024 / 1024;
11492-
*deviceRank += videoMemoryRounded;
11493-
}
11494-
11495-
1149611506
// FIXME: Need better structure for checking vs storing swapchain support details
1149711507
return 1;
1149811508
}

0 commit comments

Comments
 (0)