mirror of https://github.com/PCSX2/pcsx2.git
GS/Vulkan: Simplify GPU selection
Hopefully stops a crash on broken drivers.
This commit is contained in:
parent
388da2058b
commit
b3697579c0
|
@ -26,6 +26,8 @@
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
|
#include "fmt/format.h"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include "common/RedtapeWindows.h"
|
#include "common/RedtapeWindows.h"
|
||||||
#else
|
#else
|
||||||
|
@ -192,83 +194,60 @@ namespace Vulkan
|
||||||
|
|
||||||
Context::GPUList Context::EnumerateGPUs(VkInstance instance)
|
Context::GPUList Context::EnumerateGPUs(VkInstance instance)
|
||||||
{
|
{
|
||||||
|
GPUList gpus;
|
||||||
|
|
||||||
u32 gpu_count = 0;
|
u32 gpu_count = 0;
|
||||||
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
|
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
|
||||||
if ((res != VK_SUCCESS && res != VK_INCOMPLETE) || gpu_count == 0)
|
if ((res != VK_SUCCESS && res != VK_INCOMPLETE) || gpu_count == 0)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (1) failed: ");
|
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (1) failed: ");
|
||||||
return {};
|
return gpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
GPUList gpus;
|
std::vector<VkPhysicalDevice> physical_devices(gpu_count);
|
||||||
gpus.resize(gpu_count);
|
res = vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices.data());
|
||||||
|
|
||||||
res = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data());
|
|
||||||
if (res == VK_INCOMPLETE)
|
if (res == VK_INCOMPLETE)
|
||||||
{
|
{
|
||||||
Console.Warning("First vkEnumeratePhysicalDevices() call returned %zu devices, but second returned %u", gpus.size(), gpu_count);
|
Console.Warning("First vkEnumeratePhysicalDevices() call returned %zu devices, but second returned %u",
|
||||||
|
physical_devices.size(), gpu_count);
|
||||||
}
|
}
|
||||||
else if (res != VK_SUCCESS)
|
else if (res != VK_SUCCESS)
|
||||||
{
|
{
|
||||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (2) failed: ");
|
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (2) failed: ");
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
// Maybe we lost a GPU?
|
|
||||||
if (gpu_count < gpus.size())
|
|
||||||
gpus.resize(gpu_count);
|
|
||||||
|
|
||||||
return gpus;
|
return gpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
Context::GPUNameList Context::EnumerateGPUNames(VkInstance instance)
|
// Maybe we lost a GPU?
|
||||||
{
|
if (gpu_count < physical_devices.size())
|
||||||
u32 gpu_count = 0;
|
physical_devices.resize(gpu_count);
|
||||||
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
|
|
||||||
if (res != VK_SUCCESS || gpu_count == 0)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
GPUList gpus;
|
gpus.reserve(physical_devices.size());
|
||||||
gpus.resize(gpu_count);
|
for (VkPhysicalDevice device : physical_devices)
|
||||||
|
|
||||||
res = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data());
|
|
||||||
if (res != VK_SUCCESS)
|
|
||||||
{
|
|
||||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
GPUNameList gpu_names;
|
|
||||||
gpu_names.reserve(gpu_count);
|
|
||||||
for (u32 i = 0; i < gpu_count; i++)
|
|
||||||
{
|
{
|
||||||
VkPhysicalDeviceProperties props = {};
|
VkPhysicalDeviceProperties props = {};
|
||||||
vkGetPhysicalDeviceProperties(gpus[i], &props);
|
vkGetPhysicalDeviceProperties(device, &props);
|
||||||
|
|
||||||
std::string gpu_name(props.deviceName);
|
std::string gpu_name = props.deviceName;
|
||||||
|
|
||||||
// handle duplicate adapter names
|
// handle duplicate adapter names
|
||||||
if (std::any_of(gpu_names.begin(), gpu_names.end(),
|
if (std::any_of(gpus.begin(), gpus.end(),
|
||||||
[&gpu_name](const std::string& other) { return (gpu_name == other); }))
|
[&gpu_name](const auto& other) { return (gpu_name == other.second); }))
|
||||||
{
|
{
|
||||||
std::string original_adapter_name = std::move(gpu_name);
|
std::string original_adapter_name = std::move(gpu_name);
|
||||||
|
|
||||||
u32 current_extra = 2;
|
u32 current_extra = 2;
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
gpu_name = StringUtil::StdStringFromFormat("%s (%u)", original_adapter_name.c_str(), current_extra);
|
gpu_name = fmt::format("{} ({})", original_adapter_name, current_extra);
|
||||||
current_extra++;
|
current_extra++;
|
||||||
} while (std::any_of(gpu_names.begin(), gpu_names.end(),
|
} while (std::any_of(gpus.begin(), gpus.end(),
|
||||||
[&gpu_name](const std::string& other) { return (gpu_name == other); }));
|
[&gpu_name](const auto& other) { return (gpu_name == other.second); }));
|
||||||
}
|
}
|
||||||
|
|
||||||
gpu_names.push_back(std::move(gpu_name));
|
gpus.emplace_back(device, std::move(gpu_name));
|
||||||
}
|
}
|
||||||
|
|
||||||
return gpu_names;
|
return gpus;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Context::Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
|
bool Context::Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
|
||||||
|
|
|
@ -66,10 +66,8 @@ namespace Vulkan
|
||||||
const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer);
|
const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer);
|
||||||
|
|
||||||
// Returns a list of Vulkan-compatible GPUs.
|
// Returns a list of Vulkan-compatible GPUs.
|
||||||
using GPUList = std::vector<VkPhysicalDevice>;
|
using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>;
|
||||||
using GPUNameList = std::vector<std::string>;
|
|
||||||
static GPUList EnumerateGPUs(VkInstance instance);
|
static GPUList EnumerateGPUs(VkInstance instance);
|
||||||
static GPUNameList EnumerateGPUNames(VkInstance instance);
|
|
||||||
|
|
||||||
// Creates a new context and sets it up as global.
|
// Creates a new context and sets it up as global.
|
||||||
static bool Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
|
static bool Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
|
||||||
|
|
|
@ -86,6 +86,15 @@ GSDeviceVK::~GSDeviceVK()
|
||||||
pxAssert(!g_vulkan_context);
|
pxAssert(!g_vulkan_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void GPUListToAdapterNames(std::vector<std::string>* dest, VkInstance instance)
|
||||||
|
{
|
||||||
|
Vulkan::Context::GPUList gpus = Vulkan::Context::EnumerateGPUs(instance);
|
||||||
|
dest->clear();
|
||||||
|
dest->reserve(gpus.size());
|
||||||
|
for (auto& [gpu, name] : gpus)
|
||||||
|
dest->push_back(std::move(name));
|
||||||
|
}
|
||||||
|
|
||||||
void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
||||||
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes)
|
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes)
|
||||||
{
|
{
|
||||||
|
@ -94,7 +103,7 @@ void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
||||||
if (g_vulkan_context)
|
if (g_vulkan_context)
|
||||||
{
|
{
|
||||||
if (adapters)
|
if (adapters)
|
||||||
*adapters = Vulkan::Context::EnumerateGPUNames(g_vulkan_context->GetVulkanInstance());
|
GPUListToAdapterNames(adapters, g_vulkan_context->GetVulkanInstance());
|
||||||
|
|
||||||
if (fullscreen_modes)
|
if (fullscreen_modes)
|
||||||
{
|
{
|
||||||
|
@ -111,7 +120,7 @@ void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
||||||
if (instance != VK_NULL_HANDLE)
|
if (instance != VK_NULL_HANDLE)
|
||||||
{
|
{
|
||||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||||
*adapters = Vulkan::Context::EnumerateGPUNames(instance);
|
GPUListToAdapterNames(adapters, instance);
|
||||||
|
|
||||||
vkDestroyInstance(instance, nullptr);
|
vkDestroyInstance(instance, nullptr);
|
||||||
}
|
}
|
||||||
|
@ -606,26 +615,25 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 gpu_index = 0;
|
u32 gpu_index = 0;
|
||||||
Vulkan::Context::GPUNameList gpu_names = Vulkan::Context::EnumerateGPUNames(instance);
|
|
||||||
if (!GSConfig.Adapter.empty())
|
if (!GSConfig.Adapter.empty())
|
||||||
{
|
{
|
||||||
for (; gpu_index < static_cast<u32>(gpu_names.size()); gpu_index++)
|
for (; gpu_index < static_cast<u32>(gpus.size()); gpu_index++)
|
||||||
{
|
{
|
||||||
Console.WriteLn(fmt::format("GPU {}: {}", gpu_index, gpu_names[gpu_index]));
|
Console.WriteLn(fmt::format("GPU {}: {}", gpu_index, gpus[gpu_index].second));
|
||||||
if (gpu_names[gpu_index] == GSConfig.Adapter)
|
if (gpus[gpu_index].second == GSConfig.Adapter)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gpu_index == static_cast<u32>(gpu_names.size()))
|
if (gpu_index == static_cast<u32>(gpus.size()))
|
||||||
{
|
{
|
||||||
Console.Warning(
|
Console.Warning(
|
||||||
fmt::format("Requested GPU '{}' not found, using first ({})", GSConfig.Adapter, gpu_names[0]));
|
fmt::format("Requested GPU '{}' not found, using first ({})", GSConfig.Adapter, gpus[0].second));
|
||||||
gpu_index = 0;
|
gpu_index = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Console.WriteLn("No GPU requested, using first (%s)", gpu_names[0].c_str());
|
Console.WriteLn(fmt::format("No GPU requested, using first ({})", gpus[0].second));
|
||||||
}
|
}
|
||||||
|
|
||||||
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
VkSurfaceKHR surface = VK_NULL_HANDLE;
|
||||||
|
@ -635,12 +643,12 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
||||||
};
|
};
|
||||||
if (m_window_info.type != WindowInfo::Type::Surfaceless)
|
if (m_window_info.type != WindowInfo::Type::Surfaceless)
|
||||||
{
|
{
|
||||||
surface = Vulkan::SwapChain::CreateVulkanSurface(instance, gpus[gpu_index], &m_window_info);
|
surface = Vulkan::SwapChain::CreateVulkanSurface(instance, gpus[gpu_index].first, &m_window_info);
|
||||||
if (surface == VK_NULL_HANDLE)
|
if (surface == VK_NULL_HANDLE)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!Vulkan::Context::Create(instance, surface, gpus[gpu_index], !GSConfig.DisableThreadedPresentation,
|
if (!Vulkan::Context::Create(instance, surface, gpus[gpu_index].first, !GSConfig.DisableThreadedPresentation,
|
||||||
enable_debug_utils, enable_validation_layer))
|
enable_debug_utils, enable_validation_layer))
|
||||||
{
|
{
|
||||||
Console.Error("Failed to create Vulkan context");
|
Console.Error("Failed to create Vulkan context");
|
||||||
|
|
Loading…
Reference in New Issue