1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-22 10:42:36 +01:00

Fix race in render_creator (#9939)

This commit is contained in:
Eladash 2021-03-18 11:09:42 +02:00 committed by GitHub
parent 43ac33c2b4
commit ad49c54531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -31,43 +31,49 @@ render_creator::render_creator(QObject *parent) : QObject(parent)
static std::mutex mtx;
static std::condition_variable cond;
static bool thread_running = true;
static bool device_found = false;
static bool work_done = false;
static QStringList compatible_gpus;
auto enum_thread_v = new named_thread("Vulkan Device Enumeration Thread"sv, [&]()
auto enum_thread_v = new named_thread("Vulkan Device Enumeration Thread"sv, [&, adapters = &this->vulkan_adapters]()
{
thread_ctrl::scoped_priority low_prio(-1);
vk::instance device_enum_context;
std::unique_lock lock(mtx, std::defer_lock);
if (device_enum_context.create("RPCS3", true))
{
device_enum_context.bind();
std::vector<vk::physical_device>& gpus = device_enum_context.enumerate_devices();
if (!gpus.empty())
{
device_found = true;
lock.lock();
if (!work_done) // The spawning thread gave up, do not attempt to modify vulkan_adapters
{
for (auto& gpu : gpus)
{
compatible_gpus.append(qstr(gpu.get_name()));
adapters->append(qstr(gpu.get_name()));
}
}
}
else
{
lock.lock();
}
std::scoped_lock{ mtx }, thread_running = false;
work_done = true;
lock.unlock();
cond.notify_all();
});
std::unique_ptr<std::remove_pointer_t<decltype(enum_thread_v)>> enum_thread(enum_thread_v);
if ([&]()
{
std::unique_lock lck(mtx);
cond.wait_for(lck, std::chrono::seconds(10), [&] { return !thread_running; });
}
if (thread_running)
cond.wait_for(lck, std::chrono::seconds(10), [&] { return work_done; });
return !std::exchange(work_done, true); // If thread hasn't done its job yet, it won't anymore
}())
{
enum_thread.release(); // Detach thread (destructor is not called)
@ -88,8 +94,7 @@ render_creator::render_creator(QObject *parent) : QObject(parent)
}
else
{
supports_vulkan = device_found;
vulkan_adapters = std::move(compatible_gpus);
supports_vulkan = !vulkan_adapters.isEmpty();
enum_thread.reset(); // Join thread
}
#endif