@@ -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,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