gpu: Move device ranking to a standalone function.
This allows us to treat Dozen as an "other" driver, rather than blacklisting it outright.
This commit is contained in:
@@ -81,22 +81,6 @@ typedef struct VulkanExtensions
|
|||||||
|
|
||||||
// Conversions
|
// 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[] = {
|
static VkPresentModeKHR SDLToVK_PresentMode[] = {
|
||||||
VK_PRESENT_MODE_FIFO_KHR,
|
VK_PRESENT_MODE_FIFO_KHR,
|
||||||
VK_PRESENT_MODE_IMMEDIATE_KHR,
|
VK_PRESENT_MODE_IMMEDIATE_KHR,
|
||||||
@@ -11307,35 +11291,62 @@ static Uint8 VULKAN_INTERNAL_CreateInstance(VulkanRenderer *renderer)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
|
static bool VULKAN_INTERNAL_GetDeviceRank(
|
||||||
VulkanRenderer *renderer,
|
VulkanRenderer *renderer,
|
||||||
VkPhysicalDevice physicalDevice,
|
VkPhysicalDevice physicalDevice,
|
||||||
VulkanExtensions *physicalDeviceExtensions,
|
VulkanExtensions *physicalDeviceExtensions,
|
||||||
Uint32 *queueFamilyIndex,
|
|
||||||
Uint64 *deviceRank)
|
Uint64 *deviceRank)
|
||||||
{
|
{
|
||||||
Uint32 queueFamilyCount, queueFamilyRank, queueFamilyBest;
|
static const Uint8 DEVICE_PRIORITY_HIGHPERFORMANCE[] = {
|
||||||
VkQueueFamilyProperties *queueProps;
|
0, // VK_PHYSICAL_DEVICE_TYPE_OTHER
|
||||||
bool supportsPresent;
|
3, // VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU
|
||||||
VkPhysicalDeviceProperties deviceProperties;
|
4, // VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
|
||||||
VkPhysicalDeviceFeatures deviceFeatures;
|
2, // VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU
|
||||||
VkPhysicalDeviceMemoryProperties deviceMemory;
|
1 // VK_PHYSICAL_DEVICE_TYPE_CPU
|
||||||
Uint32 i;
|
};
|
||||||
|
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;
|
const Uint8 *devicePriority = renderer->preferLowPower ? DEVICE_PRIORITY_LOWPOWER : DEVICE_PRIORITY_HIGHPERFORMANCE;
|
||||||
|
|
||||||
/* Get the device rank before doing any checks, in case one fails.
|
VkPhysicalDeviceType deviceType;
|
||||||
* Note: If no dedicated device exists, one that supports our features
|
if (physicalDeviceExtensions->MSFT_layered_driver) {
|
||||||
* would be fine
|
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
|
||||||
*/
|
VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
|
||||||
renderer->vkGetPhysicalDeviceProperties(
|
|
||||||
physicalDevice,
|
physicalDeviceProperties.sType =
|
||||||
&deviceProperties);
|
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.
|
/* 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.
|
* 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) {
|
if (*deviceRank < devicePriorityValue) {
|
||||||
/* This device outranks the best device we've found so far!
|
/* 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
|
* run a query and reset the rank to avoid overwrites
|
||||||
*/
|
*/
|
||||||
*deviceRank = 0;
|
*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(
|
renderer->vkGetPhysicalDeviceFeatures(
|
||||||
physicalDevice,
|
physicalDevice,
|
||||||
&deviceFeatures);
|
&deviceFeatures);
|
||||||
@@ -11373,26 +11425,13 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore Dozen, for now
|
// Device rank depends on extension support, do NOT move this block any higher!
|
||||||
if (renderer->supports.MSFT_layered_driver) {
|
if (!VULKAN_INTERNAL_GetDeviceRank(
|
||||||
VkPhysicalDeviceProperties2KHR physicalDeviceProperties;
|
renderer,
|
||||||
VkPhysicalDeviceLayeredDriverPropertiesMSFT physicalDeviceLayeredDriverProperties;
|
physicalDevice,
|
||||||
|
physicalDeviceExtensions,
|
||||||
physicalDeviceProperties.sType =
|
deviceRank)) {
|
||||||
VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
|
return 0;
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
|
renderer->vkGetPhysicalDeviceQueueFamilyProperties(
|
||||||
@@ -11469,30 +11508,6 @@ static Uint8 VULKAN_INTERNAL_IsDeviceSuitable(
|
|||||||
return 0;
|
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
|
// FIXME: Need better structure for checking vs storing swapchain support details
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user