Add timeout for vulkan device enumeration

This commit is contained in:
msuih 2019-06-27 18:18:24 +03:00 committed by kd-11
parent 232a35b6fc
commit e043412be4

View File

@ -1,8 +1,14 @@
#include "emu_settings.h" #include "emu_settings.h"
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <mutex>
#include "stdafx.h" #include "stdafx.h"
#include "Emu/System.h" #include "Emu/System.h"
#include "Utilities/Config.h" #include "Utilities/Config.h"
#include "Utilities/Thread.h"
#include <QMessageBox> #include <QMessageBox>
@ -146,7 +152,25 @@ emu_settings::Render_Creator::Render_Creator()
#endif #endif
#if defined(WIN32) || defined(HAVE_VULKAN) #if defined(WIN32) || defined(HAVE_VULKAN)
// check for vulkan adapters // Some drivers can get stuck when checking for vulkan-compatible gpus, f.ex. if they're waiting for one to get
// plugged in. This whole contraption is for showing an error message in case that happens, so that user has
// some idea about why the emulator window isn't showing up.
static std::atomic<bool> was_called = false;
if (was_called.exchange(true))
fmt::throw_exception("Render_Creator cannot be created more than once" HERE);
static std::mutex mtx;
static std::condition_variable cond;
static bool thread_running = true;
static volatile bool device_found = false;
static QStringList compatible_gpus;
thread_ctrl::spawn("Vulkan device enumeration", [&]
{
thread_ctrl::set_native_priority(-1);
vk::context device_enum_context; vk::context device_enum_context;
u32 instance_handle = device_enum_context.createInstance("RPCS3", true); u32 instance_handle = device_enum_context.createInstance("RPCS3", true);
@ -157,15 +181,42 @@ emu_settings::Render_Creator::Render_Creator()
if (!gpus.empty()) if (!gpus.empty())
{ {
//A device with vulkan support found. Init data device_found = true;
supportsVulkan = true;
for (auto &gpu : gpus) for (auto &gpu : gpus)
{ {
vulkanAdapters.append(qstr(gpu.get_name())); compatible_gpus.append(qstr(gpu.get_name()));
} }
} }
} }
std::scoped_lock{mtx}, thread_running = false;
cond.notify_all();
});
{
std::unique_lock lck(mtx);
cond.wait_for(lck, std::chrono::seconds(10), [&]{ return !thread_running; });
}
if (thread_running)
{
LOG_ERROR(GENERAL, "Vulkan device enumeration timed out");
auto button = QMessageBox::critical(nullptr, tr("Vulkan check timeout"),
tr("Querying for Vulkan-compatible devices is taking too long. This is usually caused by malfunctioning "
"graphics drivers, reinstalling them could fix the issue.\n\n"
"Selecting ignore starts the emulator without Vulkan support."),
QMessageBox::Ignore | QMessageBox::Abort, QMessageBox::Abort);
if (button != QMessageBox::Ignore)
std::exit(1);
supportsVulkan = false;
}
else
{
supportsVulkan = device_found;
vulkanAdapters = std::move(compatible_gpus);
}
#endif #endif
// Graphics Adapter // Graphics Adapter