@@ -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-
10084static 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