Skip to content

Commit 82a3737

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 82a3737

File tree

1 file changed

+94
-79
lines changed

1 file changed

+94
-79
lines changed

src/gpu/vulkan/SDL_gpu_vulkan.c

Lines changed: 94 additions & 79 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,62 @@ 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,
1131311297
VulkanExtensions *physicalDeviceExtensions,
11314-
Uint32 *queueFamilyIndex,
1131511298
Uint64 *deviceRank)
1131611299
{
11317-
Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
11318-
VkQueueFamilyProperties *queueProps;
11319-
bool supportsPresent;
11320-
VkPhysicalDeviceProperties deviceProperties;
11321-
VkPhysicalDeviceFeatures deviceFeatures;
11322-
VkPhysicalDeviceMemoryProperties deviceMemory;
11323-
Uint32 i;
11324-
11300+
static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
11301+
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
11302+
3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
11303+
4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
11304+
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
11305+
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
11306+
};
11307+
static const Uint8 DEVICE_PRIORITY_LOWPOWER[] = {
11308+
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
11309+
4, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
11310+
3, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
11311+
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
11312+
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
11313+
};
1132511314
const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
1132611315

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);
11316+
VkPhysicalDeviceType deviceType;
11317+
if (physicalDeviceExtensions->MSFT_layered_driver) {
11318+
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
11319+
VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
11320+
11321+
physicalDeviceProperties.sType =
11322+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
11323+
physicalDeviceProperties.pNext = &physicalDeviceLayeredDriverProperties;
11324+
11325+
physicalDeviceLayeredDriverProperties.sType =
11326+
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
11327+
physicalDeviceLayeredDriverProperties.pNext = NULL;
11328+
11329+
renderer->vkGetPhysicalDeviceProperties2KHR(
11330+
physicalDevice,
11331+
&physicalDeviceProperties);
11332+
11333+
if (physicalDeviceLayeredDriverProperties.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
11334+
deviceType = VK_PHYSICAL_DEVICE_TYPE_OTHER;
11335+
} else {
11336+
deviceType = physicalDeviceProperties.properties.deviceType;
11337+
}
11338+
} else {
11339+
VkPhysicalDeviceProperties physicalDeviceProperties;
11340+
renderer->vkGetPhysicalDeviceProperties(
11341+
physicalDevice,
11342+
&physicalDeviceProperties);
11343+
deviceType = physicalDeviceProperties.deviceType;
11344+
}
1133411345

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

1134011351
if (*deviceRank < devicePriorityValue) {
1134111352
/* This device outranks the best device we've found so far!
@@ -11349,9 +11360,50 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1134911360
* run a query and reset the rank to avoid overwrites
1135011361
*/
1135111362
*deviceRank = 0;
11352-
return 0;
11363+
return false;
1135311364
}
1135411365

11366+
/* If we prefer high performance, sum up all device local memory (rounded to megabytes)
11367+
* to deviceRank. In the niche case of someone having multiple dedicated GPUs in the same
11368+
* system, this theoretically picks the most powerful one (or at least the one with the
11369+
* most memory!)
11370+
*
11371+
* We do this *after* discarding all non suitable devices, which means if this computer
11372+
* has multiple dedicated GPUs that all meet our criteria, *and* the user asked for high
11373+
* performance, then we always pick the GPU with more VRAM.
11374+
*/
11375+
if (!renderer->preferLowPower) {
11376+
Uint32 i;
11377+
Uint64 videoMemory = 0;
11378+
VkPhysicalDeviceMemoryProperties deviceMemory;
11379+
renderer->vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemory);
11380+
for (i = 0; i < deviceMemory.memoryHeapCount; i++) {
11381+
VkMemoryHeap heap = deviceMemory.memoryHeaps[i];
11382+
if (heap.flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
11383+
videoMemory += heap.size;
11384+
}
11385+
}
11386+
// Round it to megabytes (as per the vulkan spec videoMemory is in bytes)
11387+
Uint64 videoMemoryRounded = videoMemory / 1024 / 1024;
11388+
*deviceRank += videoMemoryRounded;
11389+
}
11390+
11391+
return true;
11392+
}
11393+
11394+
static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
11395+
VulkanRenderer *renderer,
11396+
VkPhysicalDevice physicalDevice,
11397+
VulkanExtensions *physicalDeviceExtensions,
11398+
Uint32 *queueFamilyIndex,
11399+
Uint64 *deviceRank)
11400+
{
11401+
Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
11402+
VkQueueFamilyProperties *queueProps;
11403+
bool supportsPresent;
11404+
VkPhysicalDeviceFeatures deviceFeatures;
11405+
Uint32 i;
11406+
1135511407
renderer->vkGetPhysicalDeviceFeatures(
1135611408
physicalDevice,
1135711409
&deviceFeatures);
@@ -11373,26 +11425,13 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1137311425
return 0;
1137411426
}
1137511427

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-
}
11428+
// Device rank depends on extension support, do NOT move this block any higher!
11429+
if (!VULKAN_INTERNAL_GetDeviceRank(
11430+
renderer,
11431+
physicalDevice,
11432+
physicalDeviceExtensions,
11433+
deviceRank)) {
11434+
return 0;
1139611435
}
1139711436

1139811437
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
@@ -11469,30 +11508,6 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
1146911508
return 0;
1147011509
}
1147111510

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-
1149611511
// FIXME: Need better structure for checking vs storing swapchain support details
1149711512
return 1;
1149811513
}

0 commit comments

Comments
 (0)