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 <cstring>
|
||||
|
||||
#include "fmt/format.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include "common/RedtapeWindows.h"
|
||||
#else
|
||||
|
@ -192,83 +194,60 @@ namespace Vulkan
|
|||
|
||||
Context::GPUList Context::EnumerateGPUs(VkInstance instance)
|
||||
{
|
||||
GPUList gpus;
|
||||
|
||||
u32 gpu_count = 0;
|
||||
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
|
||||
if ((res != VK_SUCCESS && res != VK_INCOMPLETE) || gpu_count == 0)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (1) failed: ");
|
||||
return {};
|
||||
return gpus;
|
||||
}
|
||||
|
||||
GPUList gpus;
|
||||
gpus.resize(gpu_count);
|
||||
|
||||
res = vkEnumeratePhysicalDevices(instance, &gpu_count, gpus.data());
|
||||
std::vector<VkPhysicalDevice> physical_devices(gpu_count);
|
||||
res = vkEnumeratePhysicalDevices(instance, &gpu_count, physical_devices.data());
|
||||
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)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices (2) failed: ");
|
||||
return {};
|
||||
return gpus;
|
||||
}
|
||||
|
||||
// Maybe we lost a GPU?
|
||||
if (gpu_count < gpus.size())
|
||||
gpus.resize(gpu_count);
|
||||
if (gpu_count < physical_devices.size())
|
||||
physical_devices.resize(gpu_count);
|
||||
|
||||
return gpus;
|
||||
}
|
||||
|
||||
Context::GPUNameList Context::EnumerateGPUNames(VkInstance instance)
|
||||
{
|
||||
u32 gpu_count = 0;
|
||||
VkResult res = vkEnumeratePhysicalDevices(instance, &gpu_count, nullptr);
|
||||
if (res != VK_SUCCESS || gpu_count == 0)
|
||||
{
|
||||
LOG_VULKAN_ERROR(res, "vkEnumeratePhysicalDevices failed: ");
|
||||
return {};
|
||||
}
|
||||
|
||||
GPUList gpus;
|
||||
gpus.resize(gpu_count);
|
||||
|
||||
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++)
|
||||
gpus.reserve(physical_devices.size());
|
||||
for (VkPhysicalDevice device : physical_devices)
|
||||
{
|
||||
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
|
||||
if (std::any_of(gpu_names.begin(), gpu_names.end(),
|
||||
[&gpu_name](const std::string& other) { return (gpu_name == other); }))
|
||||
if (std::any_of(gpus.begin(), gpus.end(),
|
||||
[&gpu_name](const auto& other) { return (gpu_name == other.second); }))
|
||||
{
|
||||
std::string original_adapter_name = std::move(gpu_name);
|
||||
|
||||
u32 current_extra = 2;
|
||||
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++;
|
||||
} while (std::any_of(gpu_names.begin(), gpu_names.end(),
|
||||
[&gpu_name](const std::string& other) { return (gpu_name == other); }));
|
||||
} while (std::any_of(gpus.begin(), gpus.end(),
|
||||
[&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,
|
||||
|
|
|
@ -66,10 +66,8 @@ namespace Vulkan
|
|||
const WindowInfo& wi, bool enable_debug_utils, bool enable_validation_layer);
|
||||
|
||||
// Returns a list of Vulkan-compatible GPUs.
|
||||
using GPUList = std::vector<VkPhysicalDevice>;
|
||||
using GPUNameList = std::vector<std::string>;
|
||||
using GPUList = std::vector<std::pair<VkPhysicalDevice, std::string>>;
|
||||
static GPUList EnumerateGPUs(VkInstance instance);
|
||||
static GPUNameList EnumerateGPUNames(VkInstance instance);
|
||||
|
||||
// Creates a new context and sets it up as global.
|
||||
static bool Create(VkInstance instance, VkSurfaceKHR surface, VkPhysicalDevice physical_device,
|
||||
|
|
|
@ -86,6 +86,15 @@ GSDeviceVK::~GSDeviceVK()
|
|||
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(
|
||||
std::vector<std::string>* adapters, std::vector<std::string>* fullscreen_modes)
|
||||
{
|
||||
|
@ -94,7 +103,7 @@ void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
|||
if (g_vulkan_context)
|
||||
{
|
||||
if (adapters)
|
||||
*adapters = Vulkan::Context::EnumerateGPUNames(g_vulkan_context->GetVulkanInstance());
|
||||
GPUListToAdapterNames(adapters, g_vulkan_context->GetVulkanInstance());
|
||||
|
||||
if (fullscreen_modes)
|
||||
{
|
||||
|
@ -111,7 +120,7 @@ void GSDeviceVK::GetAdaptersAndFullscreenModes(
|
|||
if (instance != VK_NULL_HANDLE)
|
||||
{
|
||||
if (Vulkan::LoadVulkanInstanceFunctions(instance))
|
||||
*adapters = Vulkan::Context::EnumerateGPUNames(instance);
|
||||
GPUListToAdapterNames(adapters, instance);
|
||||
|
||||
vkDestroyInstance(instance, nullptr);
|
||||
}
|
||||
|
@ -606,26 +615,25 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
|||
}
|
||||
|
||||
u32 gpu_index = 0;
|
||||
Vulkan::Context::GPUNameList gpu_names = Vulkan::Context::EnumerateGPUNames(instance);
|
||||
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]));
|
||||
if (gpu_names[gpu_index] == GSConfig.Adapter)
|
||||
Console.WriteLn(fmt::format("GPU {}: {}", gpu_index, gpus[gpu_index].second));
|
||||
if (gpus[gpu_index].second == GSConfig.Adapter)
|
||||
break;
|
||||
}
|
||||
|
||||
if (gpu_index == static_cast<u32>(gpu_names.size()))
|
||||
if (gpu_index == static_cast<u32>(gpus.size()))
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
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;
|
||||
|
@ -635,12 +643,12 @@ bool GSDeviceVK::CreateDeviceAndSwapChain()
|
|||
};
|
||||
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)
|
||||
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))
|
||||
{
|
||||
Console.Error("Failed to create Vulkan context");
|
||||
|
|
Loading…
Reference in New Issue