yuzu-qt: Load Vulkan device info at startup

Loading it when the configuration opens now incurs a noticeable delay.
We also don't need to rediscover the same data repeatedly each time the
configuration opens.

Moves vulkan device info discovery to yuzu's startup as opposed to the
configure_graphics constructor.
This commit is contained in:
lat9nq 2023-05-28 21:46:02 +00:00
parent 069d7e6be4
commit fc0c4db20d
11 changed files with 123 additions and 49 deletions

View file

@ -210,6 +210,8 @@ add_executable(yuzu
util/url_request_interceptor.h util/url_request_interceptor.h
util/util.cpp util/util.cpp
util/util.h util/util.h
vk_device_info.cpp
vk_device_info.h
compatdb.cpp compatdb.cpp
compatdb.h compatdb.h
yuzu.qrc yuzu.qrc

View file

@ -6,6 +6,7 @@
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "ui_configure.h" #include "ui_configure.h"
#include "vk_device_info.h"
#include "yuzu/configuration/config.h" #include "yuzu/configuration/config.h"
#include "yuzu/configuration/configure_audio.h" #include "yuzu/configuration/configure_audio.h"
#include "yuzu/configuration/configure_cpu.h" #include "yuzu/configuration/configure_cpu.h"
@ -28,6 +29,7 @@
ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
InputCommon::InputSubsystem* input_subsystem, InputCommon::InputSubsystem* input_subsystem,
std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_, bool enable_web_config) Core::System& system_, bool enable_web_config)
: QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()}, : QDialog(parent), ui{std::make_unique<Ui::ConfigureDialog>()},
registry(registry_), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_, registry(registry_), system{system_}, audio_tab{std::make_unique<ConfigureAudio>(system_,
@ -38,7 +40,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
general_tab{std::make_unique<ConfigureGeneral>(system_, this)}, general_tab{std::make_unique<ConfigureGeneral>(system_, this)},
graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)}, graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)},
graphics_tab{std::make_unique<ConfigureGraphics>( graphics_tab{std::make_unique<ConfigureGraphics>(
system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this)}, system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); },
this)},
hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)}, hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)},
input_tab{std::make_unique<ConfigureInput>(system_, this)}, input_tab{std::make_unique<ConfigureInput>(system_, this)},
network_tab{std::make_unique<ConfigureNetwork>(system_, this)}, network_tab{std::make_unique<ConfigureNetwork>(system_, this)},

View file

@ -4,7 +4,9 @@
#pragma once #pragma once
#include <memory> #include <memory>
#include <vector>
#include <QDialog> #include <QDialog>
#include "yuzu/vk_device_info.h"
namespace Core { namespace Core {
class System; class System;
@ -40,8 +42,9 @@ class ConfigureDialog : public QDialog {
public: public:
explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_, explicit ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,
InputCommon::InputSubsystem* input_subsystem, Core::System& system_, InputCommon::InputSubsystem* input_subsystem,
bool enable_web_config = true); std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_, bool enable_web_config = true);
~ConfigureDialog() override; ~ConfigureDialog() override;
void ApplyConfiguration(); void ApplyConfiguration();

View file

@ -1,10 +1,6 @@
// SPDX-FileCopyrightText: 2016 Citra Emulator Project // SPDX-FileCopyrightText: 2016 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
// Include this early to include Vulkan headers how we want to
#include "video_core/vulkan_common/vulkan_device.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include <algorithm> #include <algorithm>
#include <functional> #include <functional>
#include <iosfwd> #include <iosfwd>
@ -34,13 +30,11 @@
#include "common/settings.h" #include "common/settings.h"
#include "core/core.h" #include "core/core.h"
#include "ui_configure_graphics.h" #include "ui_configure_graphics.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_library.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#include "yuzu/configuration/configuration_shared.h" #include "yuzu/configuration/configuration_shared.h"
#include "yuzu/configuration/configure_graphics.h" #include "yuzu/configuration/configure_graphics.h"
#include "yuzu/qt_common.h" #include "yuzu/qt_common.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#include "yuzu/vk_device_info.h"
static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR, static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR,
VK_PRESENT_MODE_FIFO_KHR}; VK_PRESENT_MODE_FIFO_KHR};
@ -77,9 +71,10 @@ static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode)
} }
ConfigureGraphics::ConfigureGraphics(const Core::System& system_, ConfigureGraphics::ConfigureGraphics(const Core::System& system_,
std::vector<VkDeviceInfo::Record>& records_,
const std::function<void()>& expose_compute_option_, const std::function<void()>& expose_compute_option_,
QWidget* parent) QWidget* parent)
: QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, records{records_},
expose_compute_option{expose_compute_option_}, system{system_} { expose_compute_option{expose_compute_option_}, system{system_} {
vulkan_device = Settings::values.vulkan_device.GetValue(); vulkan_device = Settings::values.vulkan_device.GetValue();
RetrieveVulkanDevices(); RetrieveVulkanDevices();
@ -504,47 +499,19 @@ void ConfigureGraphics::UpdateAPILayout() {
} }
} }
void ConfigureGraphics::RetrieveVulkanDevices() try { void ConfigureGraphics::RetrieveVulkanDevices() {
if (UISettings::values.has_broken_vulkan) {
return;
}
using namespace Vulkan;
auto* window = this->window()->windowHandle();
auto wsi = QtCommon::GetWindowSystemInfo(window);
vk::InstanceDispatch dld;
const auto library = OpenLibrary();
const vk::Instance instance = CreateInstance(*library, dld, VK_API_VERSION_1_1, wsi.type);
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
vk::SurfaceKHR surface = CreateSurface(instance, wsi);
vulkan_devices.clear(); vulkan_devices.clear();
vulkan_devices.reserve(physical_devices.size()); vulkan_devices.reserve(records.size());
device_present_modes.clear(); device_present_modes.clear();
device_present_modes.reserve(physical_devices.size()); device_present_modes.reserve(records.size());
for (const VkPhysicalDevice device : physical_devices) { for (const auto& record : records) {
const auto physical_device = vk::PhysicalDevice(device, dld); vulkan_devices.push_back(QString::fromStdString(record.name));
const std::string name = physical_device.GetProperties().deviceName; device_present_modes.push_back(record.vsync_support);
const std::vector<VkPresentModeKHR> present_modes =
physical_device.GetSurfacePresentModesKHR(*surface);
vulkan_devices.push_back(QString::fromStdString(name));
device_present_modes.push_back(present_modes);
VkPhysicalDeviceDriverProperties driver_properties{}; if (record.is_intel_proprietary) {
driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
driver_properties.pNext = nullptr;
VkPhysicalDeviceProperties2 properties{};
properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
properties.pNext = &driver_properties;
dld.vkGetPhysicalDeviceProperties2(physical_device, &properties);
if (driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) {
expose_compute_option(); expose_compute_option();
} }
} }
} catch (const Vulkan::vk::Exception& exception) {
LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
} }
Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const { Settings::RendererBackend ConfigureGraphics::GetCurrentGraphicsBackend() const {

View file

@ -12,6 +12,7 @@
#include <qobjectdefs.h> #include <qobjectdefs.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include "common/common_types.h" #include "common/common_types.h"
#include "vk_device_info.h"
class QEvent; class QEvent;
class QObject; class QObject;
@ -39,6 +40,7 @@ class ConfigureGraphics : public QWidget {
public: public:
explicit ConfigureGraphics(const Core::System& system_, explicit ConfigureGraphics(const Core::System& system_,
std::vector<VkDeviceInfo::Record>& records,
const std::function<void()>& expose_compute_option_, const std::function<void()>& expose_compute_option_,
QWidget* parent = nullptr); QWidget* parent = nullptr);
~ConfigureGraphics() override; ~ConfigureGraphics() override;
@ -77,6 +79,7 @@ private:
ConfigurationShared::CheckState use_disk_shader_cache; ConfigurationShared::CheckState use_disk_shader_cache;
ConfigurationShared::CheckState use_asynchronous_gpu_emulation; ConfigurationShared::CheckState use_asynchronous_gpu_emulation;
std::vector<VkDeviceInfo::Record>& records;
std::vector<QString> vulkan_devices; std::vector<QString> vulkan_devices;
std::vector<std::vector<VkPresentModeKHR>> device_present_modes; std::vector<std::vector<VkPresentModeKHR>> device_present_modes;
std::vector<VkPresentModeKHR> std::vector<VkPresentModeKHR>

View file

@ -6,6 +6,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
#include <vector>
#include <fmt/format.h> #include <fmt/format.h>
@ -34,8 +35,10 @@
#include "yuzu/configuration/configure_system.h" #include "yuzu/configuration/configure_system.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#include "yuzu/util/util.h" #include "yuzu/util/util.h"
#include "yuzu/vk_device_info.h"
ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name, ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_) Core::System& system_)
: QDialog(parent), : QDialog(parent),
ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} { ui(std::make_unique<Ui::ConfigurePerGame>()), title_id{title_id_}, system{system_} {
@ -50,7 +53,7 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st
general_tab = std::make_unique<ConfigureGeneral>(system_, this); general_tab = std::make_unique<ConfigureGeneral>(system_, this);
graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this);
graphics_tab = std::make_unique<ConfigureGraphics>( graphics_tab = std::make_unique<ConfigureGraphics>(
system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this); system_, vk_device_records, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this);
input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this); input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);
system_tab = std::make_unique<ConfigureSystem>(system_, this); system_tab = std::make_unique<ConfigureSystem>(system_, this);

View file

@ -5,11 +5,13 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector>
#include <QDialog> #include <QDialog>
#include <QList> #include <QList>
#include "core/file_sys/vfs_types.h" #include "core/file_sys/vfs_types.h"
#include "vk_device_info.h"
#include "yuzu/configuration/config.h" #include "yuzu/configuration/config.h"
namespace Core { namespace Core {
@ -45,6 +47,7 @@ class ConfigurePerGame : public QDialog {
public: public:
// Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263 // Cannot use std::filesystem::path due to https://bugreports.qt.io/browse/QTBUG-73263
explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name, explicit ConfigurePerGame(QWidget* parent, u64 title_id_, const std::string& file_name,
std::vector<VkDeviceInfo::Record>& vk_device_records,
Core::System& system_); Core::System& system_);
~ConfigurePerGame() override; ~ConfigurePerGame() override;

View file

@ -147,6 +147,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual
#include "yuzu/startup_checks.h" #include "yuzu/startup_checks.h"
#include "yuzu/uisettings.h" #include "yuzu/uisettings.h"
#include "yuzu/util/clickable_label.h" #include "yuzu/util/clickable_label.h"
#include "yuzu/vk_device_info.h"
#ifdef YUZU_DBGHELP #ifdef YUZU_DBGHELP
#include "yuzu/mini_dump.h" #include "yuzu/mini_dump.h"
@ -440,6 +441,8 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan
renderer_status_button->setDisabled(true); renderer_status_button->setDisabled(true);
renderer_status_button->setChecked(false); renderer_status_button->setChecked(false);
} else {
VkDeviceInfo::PopulateRecords(vk_device_records, this->window()->windowHandle());
} }
#if defined(HAVE_SDL2) && !defined(_WIN32) #if defined(HAVE_SDL2) && !defined(_WIN32)
@ -3493,7 +3496,8 @@ void GMainWindow::OnConfigure() {
const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue(); const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue();
Settings::SetConfiguringGlobal(true); Settings::SetConfiguringGlobal(true);
ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(), *system, ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get(),
vk_device_records, *system,
!multiplayer_state->IsHostingPublicRoom()); !multiplayer_state->IsHostingPublicRoom());
connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this,
&GMainWindow::OnLanguageChanged); &GMainWindow::OnLanguageChanged);
@ -3764,7 +3768,7 @@ void GMainWindow::OpenPerGameConfiguration(u64 title_id, const std::string& file
const auto v_file = Core::GetGameFileFromPath(vfs, file_name); const auto v_file = Core::GetGameFileFromPath(vfs, file_name);
Settings::SetConfiguringGlobal(false); Settings::SetConfiguringGlobal(false);
ConfigurePerGame dialog(this, title_id, file_name, *system); ConfigurePerGame dialog(this, title_id, file_name, vk_device_records, *system);
dialog.LoadFromFile(v_file); dialog.LoadFromFile(v_file);
const auto result = dialog.exec(); const auto result = dialog.exec();

View file

@ -118,6 +118,10 @@ enum class ReinitializeKeyBehavior {
Warning, Warning,
}; };
namespace VkDeviceInfo {
class Record;
}
class GMainWindow : public QMainWindow { class GMainWindow : public QMainWindow {
Q_OBJECT Q_OBJECT
@ -418,6 +422,8 @@ private:
GameListPlaceholder* game_list_placeholder; GameListPlaceholder* game_list_placeholder;
std::vector<VkDeviceInfo::Record> vk_device_records;
// Status bar elements // Status bar elements
QLabel* message_label = nullptr; QLabel* message_label = nullptr;
QLabel* shader_building_label = nullptr; QLabel* shader_building_label = nullptr;

View file

@ -0,0 +1,53 @@
#include "video_core/vulkan_common/vulkan_device.h"
#include <vector>
#include "common/dynamic_library.h"
#include "video_core/vulkan_common/vulkan_instance.h"
#include "video_core/vulkan_common/vulkan_library.h"
#include "video_core/vulkan_common/vulkan_surface.h"
#include "video_core/vulkan_common/vulkan_wrapper.h"
#include "yuzu/qt_common.h"
#include "yuzu/vk_device_info.h"
namespace VkDeviceInfo {
Record::Record(std::string_view name_, const std::vector<VkPresentModeKHR>& vsync_modes_,
bool is_intel_proprietary_)
: name{name_}, vsync_support{vsync_modes_}, is_intel_proprietary{is_intel_proprietary_} {}
Record::~Record() = default;
void PopulateRecords(std::vector<Record>& records, QWindow* window) try {
using namespace Vulkan;
auto wsi = QtCommon::GetWindowSystemInfo(window);
vk::InstanceDispatch dld;
const auto library = OpenLibrary();
const vk::Instance instance = CreateInstance(*library, dld, VK_API_VERSION_1_1, wsi.type);
const std::vector<VkPhysicalDevice> physical_devices = instance.EnumeratePhysicalDevices();
vk::SurfaceKHR surface = CreateSurface(instance, wsi);
records.clear();
records.reserve(physical_devices.size());
for (const VkPhysicalDevice device : physical_devices) {
const auto physical_device = vk::PhysicalDevice(device, dld);
const std::string name = physical_device.GetProperties().deviceName;
const std::vector<VkPresentModeKHR> present_modes =
physical_device.GetSurfacePresentModesKHR(*surface);
VkPhysicalDeviceDriverProperties driver_properties{};
driver_properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;
driver_properties.pNext = nullptr;
VkPhysicalDeviceProperties2 properties{};
properties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2_KHR;
properties.pNext = &driver_properties;
dld.vkGetPhysicalDeviceProperties2(physical_device, &properties);
records.push_back(VkDeviceInfo::Record(name, present_modes,
driver_properties.driverID ==
VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS));
}
} catch (const Vulkan::vk::Exception& exception) {
LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what());
}
} // namespace VkDeviceInfo

27
src/yuzu/vk_device_info.h Normal file
View file

@ -0,0 +1,27 @@
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include "vulkan/vulkan_core.h"
namespace Settings {
enum class VSyncMode : u32;
}
// #include "common/settings.h"
namespace VkDeviceInfo {
// Short class to record Vulkan driver information for configuration purposes
class Record {
public:
explicit Record(std::string_view name, const std::vector<VkPresentModeKHR>& vsync_modes,
bool is_intel_proprietary);
~Record();
const std::string name;
const std::vector<VkPresentModeKHR> vsync_support;
const bool is_intel_proprietary;
};
void PopulateRecords(std::vector<Record>& records, QWindow* window);
} // namespace VkDeviceInfo