diff options
Diffstat (limited to 'src/yuzu')
32 files changed, 657 insertions, 150 deletions
| diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 0f8c1e6a6..2d7b9ab65 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -189,6 +189,8 @@ add_executable(yuzu      multiplayer/state.h      multiplayer/validation.h      precompiled_headers.h +    qt_common.cpp +    qt_common.h      startup_checks.cpp      startup_checks.h      uisettings.cpp diff --git a/src/yuzu/applets/qt_amiibo_settings.cpp b/src/yuzu/applets/qt_amiibo_settings.cpp index 4559df5b1..4988fcc83 100644 --- a/src/yuzu/applets/qt_amiibo_settings.cpp +++ b/src/yuzu/applets/qt_amiibo_settings.cpp @@ -8,7 +8,7 @@  #include "common/assert.h"  #include "common/string_util.h" -#include "core/hle/service/nfp/nfp_device.h" +#include "core/hle/service/nfc/common/device.h"  #include "core/hle/service/nfp/nfp_result.h"  #include "input_common/drivers/virtual_amiibo.h"  #include "input_common/main.h" @@ -22,7 +22,7 @@  QtAmiiboSettingsDialog::QtAmiiboSettingsDialog(QWidget* parent,                                                 Core::Frontend::CabinetParameters parameters_,                                                 InputCommon::InputSubsystem* input_subsystem_, -                                               std::shared_ptr<Service::NFP::NfpDevice> nfp_device_) +                                               std::shared_ptr<Service::NFC::NfcDevice> nfp_device_)      : QDialog(parent), ui(std::make_unique<Ui::QtAmiiboSettingsDialog>()),        input_subsystem{input_subsystem_}, nfp_device{std::move(nfp_device_)},        parameters(std::move(parameters_)) { @@ -52,11 +52,11 @@ void QtAmiiboSettingsDialog::LoadInfo() {          return;      } -    if (nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagFound && -        nfp_device->GetCurrentState() != Service::NFP::DeviceState::TagMounted) { +    if (nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagFound && +        nfp_device->GetCurrentState() != Service::NFC::DeviceState::TagMounted) {          return;      } -    nfp_device->Mount(Service::NFP::MountTarget::All); +    nfp_device->Mount(Service::NFP::ModelType::Amiibo, Service::NFP::MountTarget::All);      LoadAmiiboInfo();      LoadAmiiboData(); @@ -261,7 +261,7 @@ void QtAmiiboSettings::Close() const {  void QtAmiiboSettings::ShowCabinetApplet(      const Core::Frontend::CabinetCallback& callback_,      const Core::Frontend::CabinetParameters& parameters, -    std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const { +    std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const {      callback = std::move(callback_);      emit MainWindowShowAmiiboSettings(parameters, nfp_device);  } diff --git a/src/yuzu/applets/qt_amiibo_settings.h b/src/yuzu/applets/qt_amiibo_settings.h index bc389a33f..ee66a0255 100644 --- a/src/yuzu/applets/qt_amiibo_settings.h +++ b/src/yuzu/applets/qt_amiibo_settings.h @@ -23,9 +23,9 @@ namespace Ui {  class QtAmiiboSettingsDialog;  } -namespace Service::NFP { -class NfpDevice; -} // namespace Service::NFP +namespace Service::NFC { +class NfcDevice; +} // namespace Service::NFC  class QtAmiiboSettingsDialog final : public QDialog {      Q_OBJECT @@ -33,7 +33,7 @@ class QtAmiiboSettingsDialog final : public QDialog {  public:      explicit QtAmiiboSettingsDialog(QWidget* parent, Core::Frontend::CabinetParameters parameters_,                                      InputCommon::InputSubsystem* input_subsystem_, -                                    std::shared_ptr<Service::NFP::NfpDevice> nfp_device_); +                                    std::shared_ptr<Service::NFC::NfcDevice> nfp_device_);      ~QtAmiiboSettingsDialog() override;      int exec() override; @@ -52,7 +52,7 @@ private:      std::unique_ptr<Ui::QtAmiiboSettingsDialog> ui;      InputCommon::InputSubsystem* input_subsystem; -    std::shared_ptr<Service::NFP::NfpDevice> nfp_device; +    std::shared_ptr<Service::NFC::NfcDevice> nfp_device;      // Parameters sent in from the backend HLE applet.      Core::Frontend::CabinetParameters parameters; @@ -71,11 +71,11 @@ public:      void Close() const override;      void ShowCabinetApplet(const Core::Frontend::CabinetCallback& callback_,                             const Core::Frontend::CabinetParameters& parameters, -                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const override; +                           std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const override;  signals:      void MainWindowShowAmiiboSettings(const Core::Frontend::CabinetParameters& parameters, -                                      std::shared_ptr<Service::NFP::NfpDevice> nfp_device) const; +                                      std::shared_ptr<Service::NFC::NfcDevice> nfp_device) const;      void MainWindowRequestExit() const;  private: diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp index 2448e46b6..1f3f23038 100644 --- a/src/yuzu/applets/qt_profile_select.cpp +++ b/src/yuzu/applets/qt_profile_select.cpp @@ -95,6 +95,7 @@ QtProfileSelectionDialog::QtProfileSelectionDialog(      scroll_area->setLayout(layout);      connect(tree_view, &QTreeView::clicked, this, &QtProfileSelectionDialog::SelectUser); +    connect(tree_view, &QTreeView::doubleClicked, this, &QtProfileSelectionDialog::accept);      connect(controller_navigation, &ControllerNavigation::TriggerKeyboardEvent,              [this](Qt::Key key) {                  if (!this->isActiveWindow()) { diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index 4c7bf28d8..59d226113 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -1,36 +1,48 @@  // SPDX-FileCopyrightText: 2014 Citra Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <algorithm> +#include <array> +#include <cmath> +#include <cstring> +#include <string> +#include <tuple> +#include <type_traits>  #include <glad/glad.h> -#include <QApplication> +#include <QtCore/qglobal.h>  #if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA +#include <QCamera>  #include <QCameraImageCapture>  #include <QCameraInfo>  #endif +#include <QCursor> +#include <QEvent> +#include <QGuiApplication>  #include <QHBoxLayout> +#include <QKeyEvent> +#include <QLayout> +#include <QList>  #include <QMessageBox> -#include <QPainter>  #include <QScreen> -#include <QString> -#include <QStringList> +#include <QSize> +#include <QStringLiteral> +#include <QSurfaceFormat> +#include <QTimer>  #include <QWindow> +#include <QtCore/qobjectdefs.h>  #ifdef HAS_OPENGL  #include <QOffscreenSurface>  #include <QOpenGLContext>  #endif -#if !defined(WIN32) -#include <qpa/qplatformnativeinterface.h> -#endif - -#include <fmt/format.h> - -#include "common/assert.h"  #include "common/microprofile.h" +#include "common/polyfill_thread.h"  #include "common/scm_rev.h"  #include "common/settings.h" +#include "common/settings_input.h" +#include "common/thread.h"  #include "core/core.h"  #include "core/cpu_manager.h"  #include "core/frontend/framebuffer_layout.h" @@ -40,11 +52,16 @@  #include "input_common/drivers/tas_input.h"  #include "input_common/drivers/touch_screen.h"  #include "input_common/main.h" +#include "video_core/gpu.h" +#include "video_core/rasterizer_interface.h"  #include "video_core/renderer_base.h"  #include "yuzu/bootmanager.h"  #include "yuzu/main.h" +#include "yuzu/qt_common.h" -static Core::Frontend::WindowSystemType GetWindowSystemType(); +class QObject; +class QPaintEngine; +class QSurface;  EmuThread::EmuThread(Core::System& system) : m_system{system} {} @@ -154,7 +171,10 @@ public:          // disable vsync for any shared contexts          auto format = share_context->format(); -        format.setSwapInterval(main_surface ? Settings::values.use_vsync.GetValue() : 0); +        const int swap_interval = +            Settings::values.vsync_mode.GetValue() == Settings::VSyncMode::Immediate ? 0 : 1; + +        format.setSwapInterval(main_surface ? swap_interval : 0);          context = std::make_unique<QOpenGLContext>();          context->setShareContext(share_context); @@ -221,7 +241,7 @@ public:      explicit RenderWidget(GRenderWindow* parent) : QWidget(parent), render_window(parent) {          setAttribute(Qt::WA_NativeWindow);          setAttribute(Qt::WA_PaintOnScreen); -        if (GetWindowSystemType() == Core::Frontend::WindowSystemType::Wayland) { +        if (QtCommon::GetWindowSystemType() == Core::Frontend::WindowSystemType::Wayland) {              setAttribute(Qt::WA_DontCreateNativeAncestors);          }      } @@ -259,46 +279,6 @@ struct NullRenderWidget : public RenderWidget {      explicit NullRenderWidget(GRenderWindow* parent) : RenderWidget(parent) {}  }; -static Core::Frontend::WindowSystemType GetWindowSystemType() { -    // Determine WSI type based on Qt platform. -    QString platform_name = QGuiApplication::platformName(); -    if (platform_name == QStringLiteral("windows")) -        return Core::Frontend::WindowSystemType::Windows; -    else if (platform_name == QStringLiteral("xcb")) -        return Core::Frontend::WindowSystemType::X11; -    else if (platform_name == QStringLiteral("wayland")) -        return Core::Frontend::WindowSystemType::Wayland; -    else if (platform_name == QStringLiteral("wayland-egl")) -        return Core::Frontend::WindowSystemType::Wayland; -    else if (platform_name == QStringLiteral("cocoa")) -        return Core::Frontend::WindowSystemType::Cocoa; -    else if (platform_name == QStringLiteral("android")) -        return Core::Frontend::WindowSystemType::Android; - -    LOG_CRITICAL(Frontend, "Unknown Qt platform {}!", platform_name.toStdString()); -    return Core::Frontend::WindowSystemType::Windows; -} - -static Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) { -    Core::Frontend::EmuWindow::WindowSystemInfo wsi; -    wsi.type = GetWindowSystemType(); - -    // Our Win32 Qt external doesn't have the private API. -#if defined(WIN32) || defined(__APPLE__) -    wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; -#else -    QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); -    wsi.display_connection = pni->nativeResourceForWindow("display", window); -    if (wsi.type == Core::Frontend::WindowSystemType::Wayland) -        wsi.render_surface = window ? pni->nativeResourceForWindow("surface", window) : nullptr; -    else -        wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; -#endif -    wsi.render_surface_scale = window ? static_cast<float>(window->devicePixelRatio()) : 1.0f; - -    return wsi; -} -  GRenderWindow::GRenderWindow(GMainWindow* parent, EmuThread* emu_thread_,                               std::shared_ptr<InputCommon::InputSubsystem> input_subsystem_,                               Core::System& system_) @@ -904,7 +884,7 @@ bool GRenderWindow::InitRenderTarget() {      }      // Update the Window System information with the new render target -    window_info = GetWindowSystemInfo(child_widget->windowHandle()); +    window_info = QtCommon::GetWindowSystemInfo(child_widget->windowHandle());      child_widget->resize(Layout::ScreenUndocked::Width, Layout::ScreenUndocked::Height);      layout()->addWidget(child_widget); diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index bb4eca07f..b7b9d4141 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -5,27 +5,45 @@  #include <atomic>  #include <condition_variable> +#include <cstddef>  #include <memory>  #include <mutex> +#include <utility> +#include <vector> +#include <QByteArray>  #include <QImage> +#include <QObject> +#include <QPoint> +#include <QString>  #include <QStringList>  #include <QThread> -#include <QTouchEvent>  #include <QWidget> +#include <qglobal.h> +#include <qnamespace.h> +#include <qobjectdefs.h> +#include "common/common_types.h" +#include "common/logging/log.h"  #include "common/polyfill_thread.h"  #include "common/thread.h"  #include "core/frontend/emu_window.h" -class GRenderWindow;  class GMainWindow;  class QCamera;  class QCameraImageCapture; +class QCloseEvent; +class QFocusEvent;  class QKeyEvent; +class QMouseEvent; +class QObject; +class QResizeEvent; +class QShowEvent; +class QTimer; +class QTouchEvent; +class QWheelEvent;  namespace Core { -enum class SystemResultStatus : u32;  class System;  } // namespace Core @@ -40,7 +58,6 @@ enum class TasState;  namespace VideoCore {  enum class LoadCallbackStage; -class RendererBase;  } // namespace VideoCore  class EmuThread final : public QThread { diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index bb731276e..70737c54e 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -6,6 +6,7 @@  #include <QSettings>  #include "common/fs/fs.h"  #include "common/fs/path_util.h" +#include "common/settings.h"  #include "core/core.h"  #include "core/hle/service/acc/profile_manager.h"  #include "core/hle/service/hid/controllers/npad.h" @@ -442,6 +443,7 @@ void Config::ReadControlValues() {      ReadBasicSetting(Settings::values.mouse_panning_sensitivity);      ReadBasicSetting(Settings::values.enable_joycon_driver);      ReadBasicSetting(Settings::values.enable_procon_driver); +    ReadBasicSetting(Settings::values.random_amiibo_id);      ReadBasicSetting(Settings::values.tas_enable);      ReadBasicSetting(Settings::values.tas_loop); @@ -497,7 +499,7 @@ void Config::ReadCoreValues() {      qt_config->beginGroup(QStringLiteral("Core"));      ReadGlobalSetting(Settings::values.use_multi_core); -    ReadGlobalSetting(Settings::values.use_extended_memory_layout); +    ReadGlobalSetting(Settings::values.use_unsafe_extended_memory_layout);      qt_config->endGroup();  } @@ -692,6 +694,7 @@ void Config::ReadRendererValues() {      qt_config->beginGroup(QStringLiteral("Renderer"));      ReadGlobalSetting(Settings::values.renderer_backend); +    ReadGlobalSetting(Settings::values.async_presentation);      ReadGlobalSetting(Settings::values.renderer_force_max_clock);      ReadGlobalSetting(Settings::values.vulkan_device);      ReadGlobalSetting(Settings::values.fullscreen_mode); @@ -708,17 +711,21 @@ void Config::ReadRendererValues() {      ReadGlobalSetting(Settings::values.nvdec_emulation);      ReadGlobalSetting(Settings::values.accelerate_astc);      ReadGlobalSetting(Settings::values.async_astc); -    ReadGlobalSetting(Settings::values.use_vsync); +    ReadGlobalSetting(Settings::values.use_reactive_flushing);      ReadGlobalSetting(Settings::values.shader_backend);      ReadGlobalSetting(Settings::values.use_asynchronous_shaders);      ReadGlobalSetting(Settings::values.use_fast_gpu_time); -    ReadGlobalSetting(Settings::values.use_pessimistic_flushes);      ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); +    ReadGlobalSetting(Settings::values.enable_compute_pipelines);      ReadGlobalSetting(Settings::values.bg_red);      ReadGlobalSetting(Settings::values.bg_green);      ReadGlobalSetting(Settings::values.bg_blue);      if (global) { +        Settings::values.vsync_mode.SetValue(static_cast<Settings::VSyncMode>( +            ReadSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), +                        static_cast<u32>(Settings::values.vsync_mode.GetDefault())) +                .value<u32>()));          ReadBasicSetting(Settings::values.renderer_debug);          ReadBasicSetting(Settings::values.renderer_shader_feedback);          ReadBasicSetting(Settings::values.enable_nsight_aftermath); @@ -1145,6 +1152,7 @@ void Config::SaveControlValues() {      WriteBasicSetting(Settings::values.enable_raw_input);      WriteBasicSetting(Settings::values.enable_joycon_driver);      WriteBasicSetting(Settings::values.enable_procon_driver); +    WriteBasicSetting(Settings::values.random_amiibo_id);      WriteBasicSetting(Settings::values.keyboard_enabled);      WriteBasicSetting(Settings::values.emulate_analog_keyboard);      WriteBasicSetting(Settings::values.mouse_panning_sensitivity); @@ -1161,7 +1169,7 @@ void Config::SaveCoreValues() {      qt_config->beginGroup(QStringLiteral("Core"));      WriteGlobalSetting(Settings::values.use_multi_core); -    WriteGlobalSetting(Settings::values.use_extended_memory_layout); +    WriteGlobalSetting(Settings::values.use_unsafe_extended_memory_layout);      qt_config->endGroup();  } @@ -1313,6 +1321,7 @@ void Config::SaveRendererValues() {                   static_cast<u32>(Settings::values.renderer_backend.GetValue(global)),                   static_cast<u32>(Settings::values.renderer_backend.GetDefault()),                   Settings::values.renderer_backend.UsingGlobal()); +    WriteGlobalSetting(Settings::values.async_presentation);      WriteGlobalSetting(Settings::values.renderer_force_max_clock);      WriteGlobalSetting(Settings::values.vulkan_device);      WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()), @@ -1350,20 +1359,23 @@ void Config::SaveRendererValues() {                   Settings::values.nvdec_emulation.UsingGlobal());      WriteGlobalSetting(Settings::values.accelerate_astc);      WriteGlobalSetting(Settings::values.async_astc); -    WriteGlobalSetting(Settings::values.use_vsync); +    WriteGlobalSetting(Settings::values.use_reactive_flushing);      WriteSetting(QString::fromStdString(Settings::values.shader_backend.GetLabel()),                   static_cast<u32>(Settings::values.shader_backend.GetValue(global)),                   static_cast<u32>(Settings::values.shader_backend.GetDefault()),                   Settings::values.shader_backend.UsingGlobal());      WriteGlobalSetting(Settings::values.use_asynchronous_shaders);      WriteGlobalSetting(Settings::values.use_fast_gpu_time); -    WriteGlobalSetting(Settings::values.use_pessimistic_flushes);      WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); +    WriteGlobalSetting(Settings::values.enable_compute_pipelines);      WriteGlobalSetting(Settings::values.bg_red);      WriteGlobalSetting(Settings::values.bg_green);      WriteGlobalSetting(Settings::values.bg_blue);      if (global) { +        WriteSetting(QString::fromStdString(Settings::values.vsync_mode.GetLabel()), +                     static_cast<u32>(Settings::values.vsync_mode.GetValue()), +                     static_cast<u32>(Settings::values.vsync_mode.GetDefault()));          WriteBasicSetting(Settings::values.renderer_debug);          WriteBasicSetting(Settings::values.renderer_shader_feedback);          WriteBasicSetting(Settings::values.enable_nsight_aftermath); diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 2aaefcc05..8e76a819a 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp @@ -36,8 +36,9 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry_,        debug_tab_tab{std::make_unique<ConfigureDebugTab>(system_, this)},        filesystem_tab{std::make_unique<ConfigureFilesystem>(this)},        general_tab{std::make_unique<ConfigureGeneral>(system_, this)}, -      graphics_tab{std::make_unique<ConfigureGraphics>(system_, this)},        graphics_advanced_tab{std::make_unique<ConfigureGraphicsAdvanced>(system_, this)}, +      graphics_tab{std::make_unique<ConfigureGraphics>( +          system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this)},        hotkeys_tab{std::make_unique<ConfigureHotkeys>(system_.HIDCore(), this)},        input_tab{std::make_unique<ConfigureInput>(system_, this)},        network_tab{std::make_unique<ConfigureNetwork>(system_, this)}, diff --git a/src/yuzu/configuration/configure_dialog.h b/src/yuzu/configuration/configure_dialog.h index 1f724834a..a086a07c4 100644 --- a/src/yuzu/configuration/configure_dialog.h +++ b/src/yuzu/configuration/configure_dialog.h @@ -72,8 +72,8 @@ private:      std::unique_ptr<ConfigureDebugTab> debug_tab_tab;      std::unique_ptr<ConfigureFilesystem> filesystem_tab;      std::unique_ptr<ConfigureGeneral> general_tab; -    std::unique_ptr<ConfigureGraphics> graphics_tab;      std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; +    std::unique_ptr<ConfigureGraphics> graphics_tab;      std::unique_ptr<ConfigureHotkeys> hotkeys_tab;      std::unique_ptr<ConfigureInput> input_tab;      std::unique_ptr<ConfigureNetwork> network_tab; diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 207bcdc4d..26258d744 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp @@ -35,9 +35,6 @@ void ConfigureGeneral::SetConfiguration() {      ui->use_multi_core->setEnabled(runtime_lock);      ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); -    ui->use_extended_memory_layout->setEnabled(runtime_lock); -    ui->use_extended_memory_layout->setChecked( -        Settings::values.use_extended_memory_layout.GetValue());      ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue());      ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); @@ -79,9 +76,6 @@ void ConfigureGeneral::ResetDefaults() {  void ConfigureGeneral::ApplyConfiguration() {      ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core,                                               use_multi_core); -    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_extended_memory_layout, -                                             ui->use_extended_memory_layout, -                                             use_extended_memory_layout);      if (Settings::IsConfiguringGlobal()) {          UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); @@ -141,9 +135,6 @@ void ConfigureGeneral::SetupPerGameUI() {                                              Settings::values.use_speed_limit, use_speed_limit);      ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core,                                              use_multi_core); -    ConfigurationShared::SetColoredTristate(ui->use_extended_memory_layout, -                                            Settings::values.use_extended_memory_layout, -                                            use_extended_memory_layout);      connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() {          ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index a090c1a3f..7ff63f425 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h @@ -47,7 +47,6 @@ private:      ConfigurationShared::CheckState use_speed_limit;      ConfigurationShared::CheckState use_multi_core; -    ConfigurationShared::CheckState use_extended_memory_layout;      const Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index add110bb0..986a1625b 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui @@ -62,13 +62,6 @@             </widget>            </item>            <item> -           <widget class="QCheckBox" name="use_extended_memory_layout"> -            <property name="text"> -             <string>Extended memory layout (8GB DRAM)</string> -            </property> -           </widget> -          </item> -          <item>             <widget class="QCheckBox" name="toggle_check_exit">              <property name="text">               <string>Confirm exit while emulation is running</string> diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index e9388daad..f316b598c 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -2,24 +2,85 @@  // 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 <functional> +#include <iosfwd> +#include <iterator> +#include <string> +#include <tuple> +#include <utility> +#include <vector> +#include <QBoxLayout> +#include <QCheckBox>  #include <QColorDialog> -#include <QVulkanInstance> +#include <QComboBox> +#include <QIcon> +#include <QLabel> +#include <QPixmap> +#include <QPushButton> +#include <QSlider> +#include <QStringLiteral> +#include <QtCore/qobjectdefs.h> +#include <qcoreevent.h> +#include <qglobal.h> +#include <vulkan/vulkan_core.h>  #include "common/common_types.h" +#include "common/dynamic_library.h"  #include "common/logging/log.h"  #include "common/settings.h"  #include "core/core.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/configure_graphics.h" +#include "yuzu/qt_common.h"  #include "yuzu/uisettings.h" -ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* parent) -    : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, system{system_} { +static const std::vector<VkPresentModeKHR> default_present_modes{VK_PRESENT_MODE_IMMEDIATE_KHR, +                                                                 VK_PRESENT_MODE_FIFO_KHR}; + +// Converts a setting to a present mode (or vice versa) +static constexpr VkPresentModeKHR VSyncSettingToMode(Settings::VSyncMode mode) { +    switch (mode) { +    case Settings::VSyncMode::Immediate: +        return VK_PRESENT_MODE_IMMEDIATE_KHR; +    case Settings::VSyncMode::Mailbox: +        return VK_PRESENT_MODE_MAILBOX_KHR; +    case Settings::VSyncMode::FIFO: +        return VK_PRESENT_MODE_FIFO_KHR; +    case Settings::VSyncMode::FIFORelaxed: +        return VK_PRESENT_MODE_FIFO_RELAXED_KHR; +    default: +        return VK_PRESENT_MODE_FIFO_KHR; +    } +} + +static constexpr Settings::VSyncMode PresentModeToSetting(VkPresentModeKHR mode) { +    switch (mode) { +    case VK_PRESENT_MODE_IMMEDIATE_KHR: +        return Settings::VSyncMode::Immediate; +    case VK_PRESENT_MODE_MAILBOX_KHR: +        return Settings::VSyncMode::Mailbox; +    case VK_PRESENT_MODE_FIFO_KHR: +        return Settings::VSyncMode::FIFO; +    case VK_PRESENT_MODE_FIFO_RELAXED_KHR: +        return Settings::VSyncMode::FIFORelaxed; +    default: +        return Settings::VSyncMode::FIFO; +    } +} + +ConfigureGraphics::ConfigureGraphics(const Core::System& system_, +                                     const std::function<void()>& expose_compute_option_, +                                     QWidget* parent) +    : QWidget(parent), ui{std::make_unique<Ui::ConfigureGraphics>()}, +      expose_compute_option{expose_compute_option_}, system{system_} {      vulkan_device = Settings::values.vulkan_device.GetValue();      RetrieveVulkanDevices(); @@ -39,13 +100,16 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren      connect(ui->api, qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {          UpdateAPILayout(); +        PopulateVSyncModeSelection();          if (!Settings::IsConfiguringGlobal()) {              ConfigurationShared::SetHighlight(                  ui->api_widget, ui->api->currentIndex() != ConfigurationShared::USE_GLOBAL_INDEX);          }      }); -    connect(ui->device, qOverload<int>(&QComboBox::activated), this, -            [this](int device) { UpdateDeviceSelection(device); }); +    connect(ui->device, qOverload<int>(&QComboBox::activated), this, [this](int device) { +        UpdateDeviceSelection(device); +        PopulateVSyncModeSelection(); +    });      connect(ui->backend, qOverload<int>(&QComboBox::activated), this,              [this](int backend) { UpdateShaderBackendSelection(backend); }); @@ -70,6 +134,43 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren      ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal());  } +void ConfigureGraphics::PopulateVSyncModeSelection() { +    const Settings::RendererBackend backend{GetCurrentGraphicsBackend()}; +    if (backend == Settings::RendererBackend::Null) { +        ui->vsync_mode_combobox->setEnabled(false); +        return; +    } +    ui->vsync_mode_combobox->setEnabled(true); + +    const int current_index = //< current selected vsync mode from combobox +        ui->vsync_mode_combobox->currentIndex(); +    const auto current_mode = //< current selected vsync mode as a VkPresentModeKHR +        current_index == -1 ? VSyncSettingToMode(Settings::values.vsync_mode.GetValue()) +                            : vsync_mode_combobox_enum_map[current_index]; +    int index{}; +    const int device{ui->device->currentIndex()}; //< current selected Vulkan device +    const auto& present_modes = //< relevant vector of present modes for the selected device or API +        backend == Settings::RendererBackend::Vulkan ? device_present_modes[device] +                                                     : default_present_modes; + +    ui->vsync_mode_combobox->clear(); +    vsync_mode_combobox_enum_map.clear(); +    vsync_mode_combobox_enum_map.reserve(present_modes.size()); +    for (const auto present_mode : present_modes) { +        const auto mode_name = TranslateVSyncMode(present_mode, backend); +        if (mode_name.isEmpty()) { +            continue; +        } + +        ui->vsync_mode_combobox->insertItem(index, mode_name); +        vsync_mode_combobox_enum_map.push_back(present_mode); +        if (present_mode == current_mode) { +            ui->vsync_mode_combobox->setCurrentIndex(index); +        } +        index++; +    } +} +  void ConfigureGraphics::UpdateDeviceSelection(int device) {      if (device == -1) {          return; @@ -99,6 +200,9 @@ void ConfigureGraphics::SetConfiguration() {      ui->nvdec_emulation_widget->setEnabled(runtime_lock);      ui->resolution_combobox->setEnabled(runtime_lock);      ui->accelerate_astc->setEnabled(runtime_lock); +    ui->vsync_mode_layout->setEnabled(runtime_lock || +                                      Settings::values.renderer_backend.GetValue() == +                                          Settings::RendererBackend::Vulkan);      ui->use_disk_shader_cache->setChecked(Settings::values.use_disk_shader_cache.GetValue());      ui->use_asynchronous_gpu_emulation->setChecked(          Settings::values.use_asynchronous_gpu_emulation.GetValue()); @@ -170,7 +274,24 @@ void ConfigureGraphics::SetConfiguration() {                                                  Settings::values.bg_green.GetValue(),                                                  Settings::values.bg_blue.GetValue()));      UpdateAPILayout(); +    PopulateVSyncModeSelection(); //< must happen after UpdateAPILayout      SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); + +    // VSync setting needs to be determined after populating the VSync combobox +    if (Settings::IsConfiguringGlobal()) { +        const auto vsync_mode_setting = Settings::values.vsync_mode.GetValue(); +        const auto vsync_mode = VSyncSettingToMode(vsync_mode_setting); +        int index{}; +        for (const auto mode : vsync_mode_combobox_enum_map) { +            if (mode == vsync_mode) { +                break; +            } +            index++; +        } +        if (static_cast<unsigned long>(index) < vsync_mode_combobox_enum_map.size()) { +            ui->vsync_mode_combobox->setCurrentIndex(index); +        } +    }  }  void ConfigureGraphics::SetFSRIndicatorText(int percentage) { @@ -178,6 +299,27 @@ void ConfigureGraphics::SetFSRIndicatorText(int percentage) {          tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2)));  } +const QString ConfigureGraphics::TranslateVSyncMode(VkPresentModeKHR mode, +                                                    Settings::RendererBackend backend) const { +    switch (mode) { +    case VK_PRESENT_MODE_IMMEDIATE_KHR: +        return backend == Settings::RendererBackend::OpenGL +                   ? tr("Off") +                   : QStringLiteral("Immediate (%1)").arg(tr("VSync Off")); +    case VK_PRESENT_MODE_MAILBOX_KHR: +        return QStringLiteral("Mailbox (%1)").arg(tr("Recommended")); +    case VK_PRESENT_MODE_FIFO_KHR: +        return backend == Settings::RendererBackend::OpenGL +                   ? tr("On") +                   : QStringLiteral("FIFO (%1)").arg(tr("VSync On")); +    case VK_PRESENT_MODE_FIFO_RELAXED_KHR: +        return QStringLiteral("FIFO Relaxed"); +    default: +        return {}; +        break; +    } +} +  void ConfigureGraphics::ApplyConfiguration() {      const auto resolution_setup = static_cast<Settings::ResolutionSetup>(          ui->resolution_combobox->currentIndex() - @@ -232,6 +374,10 @@ void ConfigureGraphics::ApplyConfiguration() {              Settings::values.anti_aliasing.SetValue(anti_aliasing);          }          Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); + +        const auto mode = vsync_mode_combobox_enum_map[ui->vsync_mode_combobox->currentIndex()]; +        const auto vsync_mode = PresentModeToSetting(mode); +        Settings::values.vsync_mode.SetValue(vsync_mode);      } else {          if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {              Settings::values.resolution_setup.SetGlobal(true); @@ -345,7 +491,9 @@ void ConfigureGraphics::UpdateAPILayout() {          ui->backend_widget->setVisible(true);          break;      case Settings::RendererBackend::Vulkan: -        ui->device->setCurrentIndex(vulkan_device); +        if (static_cast<int>(vulkan_device) < ui->device->count()) { +            ui->device->setCurrentIndex(vulkan_device); +        }          ui->device_widget->setVisible(true);          ui->backend_widget->setVisible(false);          break; @@ -363,16 +511,37 @@ void ConfigureGraphics::RetrieveVulkanDevices() try {      using namespace Vulkan; +    auto* window = this->window()->windowHandle(); +    auto wsi = QtCommon::GetWindowSystemInfo(window); +      vk::InstanceDispatch dld;      const Common::DynamicLibrary library = OpenLibrary(); -    const vk::Instance instance = CreateInstance(library, dld, VK_API_VERSION_1_1); +    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.reserve(physical_devices.size()); +    device_present_modes.clear(); +    device_present_modes.reserve(physical_devices.size());      for (const VkPhysicalDevice device : physical_devices) { -        const std::string name = vk::PhysicalDevice(device, dld).GetProperties().deviceName; +        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);          vulkan_devices.push_back(QString::fromStdString(name)); +        device_present_modes.push_back(present_modes); + +        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); +        if (driver_properties.driverID == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS) { +            expose_compute_option(); +        }      }  } catch (const Vulkan::vk::Exception& exception) {      LOG_ERROR(Frontend, "Failed to enumerate devices with error: {}", exception.what()); @@ -465,4 +634,6 @@ void ConfigureGraphics::SetupPerGameUI() {          ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true)));      ConfigurationShared::InsertGlobalItem(          ui->nvdec_emulation, static_cast<int>(Settings::values.nvdec_emulation.GetValue(true))); + +    ui->vsync_mode_layout->setVisible(false);  } diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index d98d6624e..364b1cac2 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -3,11 +3,24 @@  #pragma once +#include <functional>  #include <memory>  #include <vector> +#include <QColor>  #include <QString>  #include <QWidget> -#include "common/settings.h" +#include <qobjectdefs.h> +#include <vulkan/vulkan_core.h> +#include "common/common_types.h" + +class QEvent; +class QObject; + +namespace Settings { +enum class NvdecEmulation : u32; +enum class RendererBackend : u32; +enum class ShaderBackend : u32; +} // namespace Settings  namespace Core {  class System; @@ -25,7 +38,9 @@ class ConfigureGraphics : public QWidget {      Q_OBJECT  public: -    explicit ConfigureGraphics(const Core::System& system_, QWidget* parent = nullptr); +    explicit ConfigureGraphics(const Core::System& system_, +                               const std::function<void()>& expose_compute_option_, +                               QWidget* parent = nullptr);      ~ConfigureGraphics() override;      void ApplyConfiguration(); @@ -35,6 +50,7 @@ private:      void changeEvent(QEvent* event) override;      void RetranslateUI(); +    void PopulateVSyncModeSelection();      void UpdateBackgroundColorButton(QColor color);      void UpdateAPILayout();      void UpdateDeviceSelection(int device); @@ -43,6 +59,10 @@ private:      void RetrieveVulkanDevices();      void SetFSRIndicatorText(int percentage); +    /* Turns a Vulkan present mode into a textual string for a UI +     * (and eventually for a human to read) */ +    const QString TranslateVSyncMode(VkPresentModeKHR mode, +                                     Settings::RendererBackend backend) const;      void SetupPerGameUI(); @@ -58,8 +78,13 @@ private:      ConfigurationShared::CheckState use_asynchronous_gpu_emulation;      std::vector<QString> vulkan_devices; +    std::vector<std::vector<VkPresentModeKHR>> device_present_modes; +    std::vector<VkPresentModeKHR> +        vsync_mode_combobox_enum_map; //< Keeps track of which present mode corresponds to which +                                      // selection in the combobox      u32 vulkan_device{};      Settings::ShaderBackend shader_backend{}; +    const std::function<void()>& expose_compute_option;      const Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index a45ec69ec..39f70e406 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -189,6 +189,44 @@           </widget>          </item>          <item> +         <widget class="QWidget" name="vsync_mode_layout" native="true"> +          <layout class="QHBoxLayout" name="horizontalLayout_4"> +           <property name="leftMargin"> +            <number>0</number> +           </property> +           <property name="topMargin"> +            <number>0</number> +           </property> +           <property name="rightMargin"> +            <number>0</number> +           </property> +           <property name="bottomMargin"> +            <number>0</number> +           </property> +           <item> +            <widget class="QLabel" name="vsync_mode_label"> +             <property name="text"> +              <string>VSync Mode:</string> +             </property> +            </widget> +           </item> +           <item> +            <widget class="QComboBox" name="vsync_mode_combobox"> +             <property name="toolTip"> +              <string>FIFO (VSync) does not drop frames or exhibit tearing but is limited by the screen refresh rate. +FIFO Relaxed is similar to FIFO but allows tearing as it recovers from a slow down. +Mailbox can have lower latency than FIFO and does not tear but may drop frames. +Immediate (no synchronization) just presents whatever is available and can exhibit tearing.</string> +             </property> +             <property name="currentText"> +              <string/> +             </property> +            </widget> +           </item> +          </layout> +         </widget> +        </item> +        <item>           <widget class="QWidget" name="nvdec_emulation_widget" native="true">            <layout class="QHBoxLayout" name="nvdec_emulation_layout">             <property name="leftMargin"> @@ -366,7 +404,7 @@               </item>               <item>                <property name="text"> -                  <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string> +               <string>1.5X (1080p/1620p) [EXPERIMENTAL]</string>                </property>               </item>               <item> diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 59fb1b334..1f3e489d0 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp @@ -15,26 +15,32 @@ ConfigureGraphicsAdvanced::ConfigureGraphicsAdvanced(const Core::System& system_      SetupPerGameUI();      SetConfiguration(); + +    ui->enable_compute_pipelines_checkbox->setVisible(false);  }  ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;  void ConfigureGraphicsAdvanced::SetConfiguration() {      const bool runtime_lock = !system.IsPoweredOn(); -    ui->use_vsync->setEnabled(runtime_lock); +    ui->use_reactive_flushing->setEnabled(runtime_lock); +    ui->async_present->setEnabled(runtime_lock);      ui->renderer_force_max_clock->setEnabled(runtime_lock);      ui->async_astc->setEnabled(runtime_lock);      ui->use_asynchronous_shaders->setEnabled(runtime_lock);      ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); +    ui->enable_compute_pipelines_checkbox->setEnabled(runtime_lock); +    ui->async_present->setChecked(Settings::values.async_presentation.GetValue());      ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); -    ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); +    ui->use_reactive_flushing->setChecked(Settings::values.use_reactive_flushing.GetValue());      ui->async_astc->setChecked(Settings::values.async_astc.GetValue());      ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue());      ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); -    ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue());      ui->use_vulkan_driver_pipeline_cache->setChecked(          Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); +    ui->enable_compute_pipelines_checkbox->setChecked( +        Settings::values.enable_compute_pipelines.GetValue());      if (Settings::IsConfiguringGlobal()) {          ui->gpu_accuracy->setCurrentIndex( @@ -54,12 +60,15 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {  void ConfigureGraphicsAdvanced::ApplyConfiguration() {      ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_presentation, +                                             ui->async_present, async_present);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.renderer_force_max_clock,                                               ui->renderer_force_max_clock,                                               renderer_force_max_clock);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy,                                               ui->anisotropic_filtering_combobox); -    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_reactive_flushing, +                                             ui->use_reactive_flushing, use_reactive_flushing);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_astc, ui->async_astc,                                               async_astc);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, @@ -67,11 +76,12 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() {                                               use_asynchronous_shaders);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time,                                               ui->use_fast_gpu_time, use_fast_gpu_time); -    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes, -                                             ui->use_pessimistic_flushes, use_pessimistic_flushes);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache,                                               ui->use_vulkan_driver_pipeline_cache,                                               use_vulkan_driver_pipeline_cache); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.enable_compute_pipelines, +                                             ui->enable_compute_pipelines_checkbox, +                                             enable_compute_pipelines);  }  void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { @@ -90,27 +100,31 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {      // Disable if not global (only happens during game)      if (Settings::IsConfiguringGlobal()) {          ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); +        ui->async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());          ui->renderer_force_max_clock->setEnabled(              Settings::values.renderer_force_max_clock.UsingGlobal()); -        ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); +        ui->use_reactive_flushing->setEnabled(Settings::values.use_reactive_flushing.UsingGlobal());          ui->async_astc->setEnabled(Settings::values.async_astc.UsingGlobal());          ui->use_asynchronous_shaders->setEnabled(              Settings::values.use_asynchronous_shaders.UsingGlobal());          ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); -        ui->use_pessimistic_flushes->setEnabled( -            Settings::values.use_pessimistic_flushes.UsingGlobal());          ui->use_vulkan_driver_pipeline_cache->setEnabled(              Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal());          ui->anisotropic_filtering_combobox->setEnabled(              Settings::values.max_anisotropy.UsingGlobal()); +        ui->enable_compute_pipelines_checkbox->setEnabled( +            Settings::values.enable_compute_pipelines.UsingGlobal());          return;      } +    ConfigurationShared::SetColoredTristate(ui->async_present, Settings::values.async_presentation, +                                            async_present);      ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock,                                              Settings::values.renderer_force_max_clock,                                              renderer_force_max_clock); -    ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); +    ConfigurationShared::SetColoredTristate( +        ui->use_reactive_flushing, Settings::values.use_reactive_flushing, use_reactive_flushing);      ConfigurationShared::SetColoredTristate(ui->async_astc, Settings::values.async_astc,                                              async_astc);      ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, @@ -118,12 +132,12 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {                                              use_asynchronous_shaders);      ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time,                                              Settings::values.use_fast_gpu_time, use_fast_gpu_time); -    ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes, -                                            Settings::values.use_pessimistic_flushes, -                                            use_pessimistic_flushes);      ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache,                                              Settings::values.use_vulkan_driver_pipeline_cache,                                              use_vulkan_driver_pipeline_cache); +    ConfigurationShared::SetColoredTristate(ui->enable_compute_pipelines_checkbox, +                                            Settings::values.enable_compute_pipelines, +                                            enable_compute_pipelines);      ConfigurationShared::SetColoredComboBox(          ui->gpu_accuracy, ui->label_gpu_accuracy,          static_cast<int>(Settings::values.gpu_accuracy.GetValue(true))); @@ -131,3 +145,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {          ui->anisotropic_filtering_combobox, ui->af_label,          static_cast<int>(Settings::values.max_anisotropy.GetValue(true)));  } + +void ConfigureGraphicsAdvanced::ExposeComputeOption() { +    ui->enable_compute_pipelines_checkbox->setVisible(true); +} diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index bf1b04749..1c7b636b9 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h @@ -28,6 +28,8 @@ public:      void ApplyConfiguration();      void SetConfiguration(); +    void ExposeComputeOption(); +  private:      void changeEvent(QEvent* event) override;      void RetranslateUI(); @@ -36,13 +38,15 @@ private:      std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; +    ConfigurationShared::CheckState async_present;      ConfigurationShared::CheckState renderer_force_max_clock;      ConfigurationShared::CheckState use_vsync;      ConfigurationShared::CheckState async_astc; +    ConfigurationShared::CheckState use_reactive_flushing;      ConfigurationShared::CheckState use_asynchronous_shaders;      ConfigurationShared::CheckState use_fast_gpu_time; -    ConfigurationShared::CheckState use_pessimistic_flushes;      ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; +    ConfigurationShared::CheckState enable_compute_pipelines;      const Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index a7dbdc18c..9ef7c8e8f 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui @@ -7,7 +7,7 @@      <x>0</x>      <y>0</y>      <width>404</width> -    <height>321</height> +    <height>376</height>     </rect>    </property>    <property name="windowTitle"> @@ -70,6 +70,13 @@           </widget>          </item>          <item> +         <widget class="QCheckBox" name="async_present"> +          <property name="text"> +           <string>Enable asynchronous presentation (Vulkan only)</string> +          </property> +         </widget> +        </item> +        <item>           <widget class="QCheckBox" name="renderer_force_max_clock">            <property name="toolTip">             <string>Runs work in the background while waiting for graphics commands to keep the GPU from lowering its clock speed.</string> @@ -80,22 +87,22 @@           </widget>          </item>          <item> -         <widget class="QCheckBox" name="use_vsync"> +         <widget class="QCheckBox" name="async_astc">            <property name="toolTip"> -           <string>VSync prevents the screen from tearing, but some graphics cards have lower performance with VSync enabled. Keep it enabled if you don't notice a performance difference.</string> +           <string>Enables asynchronous ASTC texture decoding, which may reduce load time stutter. This feature is experimental.</string>            </property>            <property name="text"> -           <string>Use VSync</string> +           <string>Decode ASTC textures asynchronously (Hack)</string>            </property>           </widget>          </item>          <item> -         <widget class="QCheckBox" name="async_astc"> +         <widget class="QCheckBox" name="use_reactive_flushing">            <property name="toolTip"> -           <string>Enables asynchronous ASTC texture decoding, which may reduce load time stutter. This feature is experimental.</string> +           <string>Uses reactive flushing instead of predictive flushing. Allowing a more accurate syncing of memory.</string>            </property>            <property name="text"> -           <string>Decode ASTC textures asynchronously (Hack)</string> +           <string>Enable Reactive Flushing</string>            </property>           </widget>          </item> @@ -112,7 +119,7 @@          <item>           <widget class="QCheckBox" name="use_fast_gpu_time">            <property name="toolTip"> -            <string>Enables Fast GPU Time. This option will force most games to run at their highest native resolution.</string> +           <string>Enables Fast GPU Time. This option will force most games to run at their highest native resolution.</string>            </property>            <property name="text">             <string>Use Fast GPU Time (Hack)</string> @@ -120,22 +127,23 @@           </widget>          </item>          <item> -         <widget class="QCheckBox" name="use_pessimistic_flushes"> +         <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache">            <property name="toolTip"> -            <string>Enables pessimistic buffer flushes. This option will force unmodified buffers to be flushed, which can cost performance.</string> +           <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string>            </property>            <property name="text"> -           <string>Use pessimistic buffer flushes (Hack)</string> +           <string>Use Vulkan pipeline cache</string>            </property>           </widget>          </item>          <item> -         <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache"> +         <widget class="QCheckBox" name="enable_compute_pipelines_checkbox">            <property name="toolTip"> -            <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string> +           <string>Enable compute pipelines, required by some games. This setting only exists for Intel proprietary drivers, and may crash if enabled. +Compute pipelines are always enabled on all other drivers.</string>            </property>            <property name="text"> -           <string>Use Vulkan pipeline cache</string> +           <string>Enable Compute Pipelines (Intel Vulkan only)</string>            </property>           </widget>          </item> diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 8d81322f3..f13156434 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -140,6 +140,7 @@ void ConfigureInputAdvanced::ApplyConfiguration() {      Settings::values.enable_ir_sensor = ui->enable_ir_sensor->isChecked();      Settings::values.enable_joycon_driver = ui->enable_joycon_driver->isChecked();      Settings::values.enable_procon_driver = ui->enable_procon_driver->isChecked(); +    Settings::values.random_amiibo_id = ui->random_amiibo_id->isChecked();  }  void ConfigureInputAdvanced::LoadConfiguration() { @@ -176,6 +177,7 @@ void ConfigureInputAdvanced::LoadConfiguration() {      ui->enable_ir_sensor->setChecked(Settings::values.enable_ir_sensor.GetValue());      ui->enable_joycon_driver->setChecked(Settings::values.enable_joycon_driver.GetValue());      ui->enable_procon_driver->setChecked(Settings::values.enable_procon_driver.GetValue()); +    ui->random_amiibo_id->setChecked(Settings::values.random_amiibo_id.GetValue());      UpdateUIEnabled();  } diff --git a/src/yuzu/configuration/configure_input_advanced.ui b/src/yuzu/configuration/configure_input_advanced.ui index 0eb2b34bc..2e8b13660 100644 --- a/src/yuzu/configuration/configure_input_advanced.ui +++ b/src/yuzu/configuration/configure_input_advanced.ui @@ -2728,6 +2728,22 @@                       </widget>                     </item>                     <item row="7" column="0"> +                     <widget class="QCheckBox" name="random_amiibo_id"> +                       <property name="toolTip"> +                         <string>Allows unlimited uses of the same Amiibo in games that would otherwise limit you to one use.</string> +                       </property> +                       <property name="minimumSize"> +                         <size> +                           <width>0</width> +                           <height>23</height> +                         </size> +                       </property> +                       <property name="text"> +                         <string>Use random Amiibo ID</string> +                       </property> +                     </widget> +                   </item> +                   <item row="8" column="0">                       <widget class="QCheckBox" name="mouse_panning">                         <property name="minimumSize">                           <size> @@ -2740,7 +2756,7 @@                         </property>                       </widget>                     </item> -                   <item row="7" column="2"> +                   <item row="8" column="2">                       <widget class="QSpinBox" name="mouse_panning_sensitivity">                         <property name="toolTip">                           <string>Mouse sensitivity</string> @@ -2762,14 +2778,14 @@                         </property>                       </widget>                     </item> -                   <item row="8" column="0"> +                   <item row="9" column="0">                       <widget class="QLabel" name="motion_touch">                         <property name="text">                           <string>Motion / Touch</string>                         </property>                       </widget>                     </item> -                   <item row="8" column="2"> +                   <item row="9" column="2">                       <widget class="QPushButton" name="buttonMotionTouch">                         <property name="text">                           <string>Configure</string> diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 50b62293e..2c2e7e47b 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp @@ -8,6 +8,7 @@  #include <QInputDialog>  #include <QMenu>  #include <QMessageBox> +#include <QMouseEvent>  #include <QTimer>  #include "common/assert.h"  #include "common/param_package.h" @@ -206,7 +207,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {          }          if (param.Has("axis")) {              const QString axis = QString::fromStdString(param.Get("axis", "")); -            return QObject::tr("%1%2Axis %3").arg(toggle, invert, axis); +            return QObject::tr("%1%2%3Axis %4").arg(toggle, inverted, invert, axis);          }          if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) {              const QString axis_x = QString::fromStdString(param.Get("axis_x", "")); @@ -229,7 +230,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) {          return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name);      }      if (param.Has("axis")) { -        return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); +        return QObject::tr("%1%2%3Axis %4").arg(toggle, inverted, invert, button_name);      }      if (param.Has("motion")) {          return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); @@ -410,6 +411,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i                              button_map[button_id]->setText(ButtonToText(param));                              emulated_controller->SetButtonParam(button_id, param);                          }); +                        context_menu.addAction(tr("Invert button"), [&] { +                            const bool invert_value = !param.Get("inverted", false); +                            param.Set("inverted", invert_value); +                            button_map[button_id]->setText(ButtonToText(param)); +                            emulated_controller->SetButtonParam(button_id, param); +                        });                          context_menu.addAction(tr("Set threshold"), [&] {                              const int button_threshold =                                  static_cast<int>(param.Get("threshold", 0.5f) * 100.0f); @@ -472,6 +479,9 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i                              param.Set("threshold", new_threshold / 1000.0f);                              emulated_controller->SetMotionParam(motion_id, param);                          }); +                        context_menu.addAction(tr("Calibrate sensor"), [&] { +                            emulated_controller->StartMotionCalibration(); +                        });                      }                      context_menu.exec(motion_map[motion_id]->mapToGlobal(menu_location));                  }); diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index c287220fc..a188eef92 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -180,6 +180,10 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ          battery_values = controller->GetBatteryValues();          needs_redraw = true;          break; +    case Core::HID::ControllerTriggerType::Motion: +        motion_values = controller->GetMotions(); +        needs_redraw = true; +        break;      default:          break;      } @@ -313,6 +317,15 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center)          DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0));      } +    { +        // Draw motion cubes +        using namespace Settings::NativeMotion; +        p.setPen(colors.outline); +        p.setBrush(colors.transparent); +        Draw3dCube(p, center + QPointF(-140, 90), +                   motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f); +    } +      using namespace Settings::NativeButton;      // D-pad constants @@ -435,6 +448,15 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center          DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90));      } +    { +        // Draw motion cubes +        using namespace Settings::NativeMotion; +        p.setPen(colors.outline); +        p.setBrush(colors.transparent); +        Draw3dCube(p, center + QPointF(140, 90), +                   motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f); +    } +      using namespace Settings::NativeButton;      // Face buttons constants @@ -555,6 +577,17 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center)          DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90));      } +    { +        // Draw motion cubes +        using namespace Settings::NativeMotion; +        p.setPen(colors.outline); +        p.setBrush(colors.transparent); +        Draw3dCube(p, center + QPointF(-180, 90), +                   motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f); +        Draw3dCube(p, center + QPointF(180, 90), +                   motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f); +    } +      using namespace Settings::NativeButton;      // Face buttons constants @@ -647,6 +680,15 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen          DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0));      } +    { +        // Draw motion cubes +        using namespace Settings::NativeMotion; +        p.setPen(colors.outline); +        p.setBrush(colors.transparent); +        Draw3dCube(p, center + QPointF(0, -115), +                   motion_values[Settings::NativeMotion::MotionLeft].euler, 15.0f); +    } +      using namespace Settings::NativeButton;      // Face buttons constants @@ -750,6 +792,15 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center)          DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105));      } +    { +        // Draw motion cubes +        using namespace Settings::NativeMotion; +        p.setPen(colors.button); +        p.setBrush(colors.transparent); +        Draw3dCube(p, center + QPointF(0, -100), +                   motion_values[Settings::NativeMotion::MotionLeft].euler, 15.0f); +    } +      using namespace Settings::NativeButton;      // Face buttons constants @@ -2871,6 +2922,46 @@ void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Di      DrawPolygon(p, arrow_symbol);  } +// Draw motion functions +void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, +                                      float size) { +    std::array<Common::Vec3f, 8> cube{ +        Common::Vec3f{-0.7f, -1, -0.5f}, +        {-0.7f, 1, -0.5f}, +        {0.7f, 1, -0.5f}, +        {0.7f, -1, -0.5f}, +        {-0.7f, -1, 0.5f}, +        {-0.7f, 1, 0.5f}, +        {0.7f, 1, 0.5f}, +        {0.7f, -1, 0.5f}, +    }; + +    for (Common::Vec3f& point : cube) { +        point.RotateFromOrigin(euler.x, euler.y, euler.z); +        point *= size; +    } + +    const std::array<QPointF, 4> front_face{ +        center + QPointF{cube[0].x, cube[0].y}, +        center + QPointF{cube[1].x, cube[1].y}, +        center + QPointF{cube[2].x, cube[2].y}, +        center + QPointF{cube[3].x, cube[3].y}, +    }; +    const std::array<QPointF, 4> back_face{ +        center + QPointF{cube[4].x, cube[4].y}, +        center + QPointF{cube[5].x, cube[5].y}, +        center + QPointF{cube[6].x, cube[6].y}, +        center + QPointF{cube[7].x, cube[7].y}, +    }; + +    DrawPolygon(p, front_face); +    DrawPolygon(p, back_face); +    p.drawLine(center + QPointF{cube[0].x, cube[0].y}, center + QPointF{cube[4].x, cube[4].y}); +    p.drawLine(center + QPointF{cube[1].x, cube[1].y}, center + QPointF{cube[5].x, cube[5].y}); +    p.drawLine(center + QPointF{cube[2].x, cube[2].y}, center + QPointF{cube[6].x, cube[6].y}); +    p.drawLine(center + QPointF{cube[3].x, cube[3].y}, center + QPointF{cube[7].x, cube[7].y}); +} +  template <size_t N>  void PlayerControlPreview::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) {      p.drawPolygon(polygon.data(), static_cast<int>(polygon.size())); diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 267d134de..a16943c3c 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -9,6 +9,7 @@  #include "common/input.h"  #include "common/settings_input.h" +#include "common/vector_math.h"  #include "core/hid/emulated_controller.h"  #include "core/hid/hid_types.h" @@ -193,6 +194,9 @@ private:      void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size);      void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); +    // Draw motion functions +    void Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, float size); +      // Draw primitive types      template <size_t N>      void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon); @@ -222,4 +226,5 @@ private:      Core::HID::SticksValues stick_values{};      Core::HID::TriggerValues trigger_values{};      Core::HID::BatteryValues battery_values{}; +    Core::HID::MotionState motion_values{};  }; diff --git a/src/yuzu/configuration/configure_per_game.cpp b/src/yuzu/configuration/configure_per_game.cpp index 7e757eafd..7ac162586 100644 --- a/src/yuzu/configuration/configure_per_game.cpp +++ b/src/yuzu/configuration/configure_per_game.cpp @@ -48,8 +48,9 @@ ConfigurePerGame::ConfigurePerGame(QWidget* parent, u64 title_id_, const std::st      audio_tab = std::make_unique<ConfigureAudio>(system_, this);      cpu_tab = std::make_unique<ConfigureCpu>(system_, this);      general_tab = std::make_unique<ConfigureGeneral>(system_, this); -    graphics_tab = std::make_unique<ConfigureGraphics>(system_, this);      graphics_advanced_tab = std::make_unique<ConfigureGraphicsAdvanced>(system_, this); +    graphics_tab = std::make_unique<ConfigureGraphics>( +        system_, [&]() { graphics_advanced_tab->ExposeComputeOption(); }, this);      input_tab = std::make_unique<ConfigureInputPerGame>(system_, game_config.get(), this);      system_tab = std::make_unique<ConfigureSystem>(system_, this); diff --git a/src/yuzu/configuration/configure_per_game.h b/src/yuzu/configuration/configure_per_game.h index 4ecc43541..85752f1fa 100644 --- a/src/yuzu/configuration/configure_per_game.h +++ b/src/yuzu/configuration/configure_per_game.h @@ -75,8 +75,8 @@ private:      std::unique_ptr<ConfigureAudio> audio_tab;      std::unique_ptr<ConfigureCpu> cpu_tab;      std::unique_ptr<ConfigureGeneral> general_tab; -    std::unique_ptr<ConfigureGraphics> graphics_tab;      std::unique_ptr<ConfigureGraphicsAdvanced> graphics_advanced_tab; +    std::unique_ptr<ConfigureGraphics> graphics_tab;      std::unique_ptr<ConfigureInputPerGame> input_tab;      std::unique_ptr<ConfigureSystem> system_tab;  }; diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 6af34f793..286ccc5cd 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp @@ -111,6 +111,9 @@ void ConfigureSystem::SetConfiguration() {      ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time));      ui->device_name_edit->setText(          QString::fromUtf8(Settings::values.device_name.GetValue().c_str())); +    ui->use_unsafe_extended_memory_layout->setEnabled(enabled); +    ui->use_unsafe_extended_memory_layout->setChecked( +        Settings::values.use_unsafe_extended_memory_layout.GetValue());      if (Settings::IsConfiguringGlobal()) {          ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); @@ -160,6 +163,9 @@ void ConfigureSystem::ApplyConfiguration() {      ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region);      ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index,                                               ui->combo_time_zone); +    ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_unsafe_extended_memory_layout, +                                             ui->use_unsafe_extended_memory_layout, +                                             use_unsafe_extended_memory_layout);      if (Settings::IsConfiguringGlobal()) {          // Guard if during game and set to game-specific value @@ -215,6 +221,10 @@ void ConfigureSystem::SetupPerGameUI() {          Settings::values.rng_seed.GetValue().has_value(),          Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); +    ConfigurationShared::SetColoredTristate(ui->use_unsafe_extended_memory_layout, +                                            Settings::values.use_unsafe_extended_memory_layout, +                                            use_unsafe_extended_memory_layout); +      ui->custom_rtc_checkbox->setVisible(false);      ui->custom_rtc_edit->setVisible(false);  } diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index ec28724a1..ce1a91601 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h @@ -41,6 +41,7 @@ private:      bool enabled = false;      ConfigurationShared::CheckState use_rng_seed; +    ConfigurationShared::CheckState use_unsafe_extended_memory_layout;      Core::System& system;  }; diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 9e7bc3b93..e0caecd5e 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui @@ -478,6 +478,13 @@              </property>             </widget>            </item> +          <item row="7" column="0"> +           <widget class="QCheckBox" name="use_unsafe_extended_memory_layout"> +            <property name="text"> +             <string>Unsafe extended memory layout (8GB DRAM)</string> +            </property> +           </widget> +          </item>           </layout>          </item>         </layout> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 519a2906f..4489f43af 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -27,6 +27,7 @@  #include "configuration/configure_input.h"  #include "configuration/configure_per_game.h"  #include "configuration/configure_tas.h" +#include "core/file_sys/romfs_factory.h"  #include "core/file_sys/vfs.h"  #include "core/file_sys/vfs_real.h"  #include "core/frontend/applets/cabinet.h" @@ -570,8 +571,8 @@ void GMainWindow::RegisterMetaTypes() {      // Cabinet Applet      qRegisterMetaType<Core::Frontend::CabinetParameters>("Core::Frontend::CabinetParameters"); -    qRegisterMetaType<std::shared_ptr<Service::NFP::NfpDevice>>( -        "std::shared_ptr<Service::NFP::NfpDevice>"); +    qRegisterMetaType<std::shared_ptr<Service::NFC::NfcDevice>>( +        "std::shared_ptr<Service::NFC::NfcDevice>");      // Controller Applet      qRegisterMetaType<Core::Frontend::ControllerParameters>("Core::Frontend::ControllerParameters"); @@ -599,7 +600,7 @@ void GMainWindow::RegisterMetaTypes() {  }  void GMainWindow::AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, -                                           std::shared_ptr<Service::NFP::NfpDevice> nfp_device) { +                                           std::shared_ptr<Service::NFC::NfcDevice> nfp_device) {      cabinet_applet =          new QtAmiiboSettingsDialog(this, parameters, input_subsystem.get(), nfp_device);      SCOPE_EXIT({ @@ -4179,6 +4180,8 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {      }      Core::Crypto::KeyManager& keys = Core::Crypto::KeyManager::Instance(); +    bool all_keys_present{true}; +      if (keys.BaseDeriveNecessary()) {          Core::Crypto::PartitionDataManager pdm{vfs->OpenDirectory("", FileSys::Mode::Read)}; @@ -4203,6 +4206,7 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {              errors += tr(" - Missing PRODINFO");          }          if (!errors.isEmpty()) { +            all_keys_present = false;              QMessageBox::warning(                  this, tr("Derivation Components Missing"),                  tr("Encryption keys are missing. " @@ -4230,11 +4234,40 @@ void GMainWindow::OnReinitializeKeys(ReinitializeKeyBehavior behavior) {      system->GetFileSystemController().CreateFactories(*vfs); +    if (all_keys_present && !this->CheckSystemArchiveDecryption()) { +        LOG_WARNING(Frontend, "Mii model decryption failed"); +        QMessageBox::warning( +            this, tr("System Archive Decryption Failed"), +            tr("Encryption keys failed to decrypt firmware. " +               "<br>Please follow <a href='https://yuzu-emu.org/help/quickstart/'>the yuzu " +               "quickstart guide</a> to get all your keys, firmware and " +               "games.")); +    } +      if (behavior == ReinitializeKeyBehavior::Warning) {          game_list->PopulateAsync(UISettings::values.game_dirs);      }  } +bool GMainWindow::CheckSystemArchiveDecryption() { +    constexpr u64 MiiModelId = 0x0100000000000802; + +    auto bis_system = system->GetFileSystemController().GetSystemNANDContents(); +    if (!bis_system) { +        // Not having system BIS files is not an error. +        return true; +    } + +    auto mii_nca = bis_system->GetEntry(MiiModelId, FileSys::ContentRecordType::Data); +    if (!mii_nca) { +        // Not having the Mii model is not an error. +        return true; +    } + +    // Return whether we are able to decrypt the RomFS of the Mii model. +    return mii_nca->GetRomFS().get() != nullptr; +} +  std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProvider& installed,                                                        u64 program_id) {      const auto dlc_entries = diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 71d78a3db..17631a2d9 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -93,9 +93,9 @@ enum class SwkbdReplyType : u32;  enum class WebExitReason : u32;  } // namespace Service::AM::Applets -namespace Service::NFP { -class NfpDevice; -} // namespace Service::NFP +namespace Service::NFC { +class NfcDevice; +} // namespace Service::NFC  namespace Ui {  class MainWindow; @@ -188,7 +188,7 @@ public slots:      void OnExit();      void OnSaveConfig();      void AmiiboSettingsShowDialog(const Core::Frontend::CabinetParameters& parameters, -                                  std::shared_ptr<Service::NFP::NfpDevice> nfp_device); +                                  std::shared_ptr<Service::NFC::NfcDevice> nfp_device);      void AmiiboSettingsRequestExit();      void ControllerSelectorReconfigureControllers(          const Core::Frontend::ControllerParameters& parameters); @@ -393,6 +393,7 @@ private:      void LoadTranslation();      void OpenPerGameConfiguration(u64 title_id, const std::string& file_name);      bool CheckDarkMode(); +    bool CheckSystemArchiveDecryption();      QString GetTasStateDescription() const;      bool CreateShortcut(const std::string& shortcut_path, const std::string& title, diff --git a/src/yuzu/qt_common.cpp b/src/yuzu/qt_common.cpp new file mode 100644 index 000000000..5d0fd7674 --- /dev/null +++ b/src/yuzu/qt_common.cpp @@ -0,0 +1,55 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#include <QGuiApplication> +#include <QStringLiteral> +#include <QWindow> +#include "common/logging/log.h" +#include "core/frontend/emu_window.h" +#include "yuzu/qt_common.h" + +#if !defined(WIN32) && !defined(__APPLE__) +#include <qpa/qplatformnativeinterface.h> +#endif + +namespace QtCommon { +Core::Frontend::WindowSystemType GetWindowSystemType() { +    // Determine WSI type based on Qt platform. +    QString platform_name = QGuiApplication::platformName(); +    if (platform_name == QStringLiteral("windows")) +        return Core::Frontend::WindowSystemType::Windows; +    else if (platform_name == QStringLiteral("xcb")) +        return Core::Frontend::WindowSystemType::X11; +    else if (platform_name == QStringLiteral("wayland")) +        return Core::Frontend::WindowSystemType::Wayland; +    else if (platform_name == QStringLiteral("wayland-egl")) +        return Core::Frontend::WindowSystemType::Wayland; +    else if (platform_name == QStringLiteral("cocoa")) +        return Core::Frontend::WindowSystemType::Cocoa; +    else if (platform_name == QStringLiteral("android")) +        return Core::Frontend::WindowSystemType::Android; + +    LOG_CRITICAL(Frontend, "Unknown Qt platform {}!", platform_name.toStdString()); +    return Core::Frontend::WindowSystemType::Windows; +} // namespace Core::Frontend::WindowSystemType + +Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window) { +    Core::Frontend::EmuWindow::WindowSystemInfo wsi; +    wsi.type = GetWindowSystemType(); + +    // Our Win32 Qt external doesn't have the private API. +#if defined(WIN32) || defined(__APPLE__) +    wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; +#else +    QPlatformNativeInterface* pni = QGuiApplication::platformNativeInterface(); +    wsi.display_connection = pni->nativeResourceForWindow("display", window); +    if (wsi.type == Core::Frontend::WindowSystemType::Wayland) +        wsi.render_surface = window ? pni->nativeResourceForWindow("surface", window) : nullptr; +    else +        wsi.render_surface = window ? reinterpret_cast<void*>(window->winId()) : nullptr; +#endif +    wsi.render_surface_scale = window ? static_cast<float>(window->devicePixelRatio()) : 1.0f; + +    return wsi; +} +} // namespace QtCommon diff --git a/src/yuzu/qt_common.h b/src/yuzu/qt_common.h new file mode 100644 index 000000000..9c63f08f3 --- /dev/null +++ b/src/yuzu/qt_common.h @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2023 yuzu Emulator Project +// SPDX-License-Identifier: GPL-2.0-or-later + +#pragma once + +#include <QWindow> +#include "core/frontend/emu_window.h" + +namespace QtCommon { + +Core::Frontend::WindowSystemType GetWindowSystemType(); + +Core::Frontend::EmuWindow::WindowSystemInfo GetWindowSystemInfo(QWindow* window); + +} // namespace QtCommon | 
