diff options
65 files changed, 909 insertions, 509 deletions
| diff --git a/CMakeLists.txt b/CMakeLists.txt index 1d13dc74e..05bffe68e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@  # SPDX-FileCopyrightText: 2018 yuzu Emulator Project  # SPDX-License-Identifier: GPL-2.0-or-later -cmake_minimum_required(VERSION 3.15) +cmake_minimum_required(VERSION 3.22)  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")  list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules") @@ -19,6 +19,9 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON  CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)  option(ENABLE_QT "Enable the Qt frontend" ON) +option(ENABLE_QT6 "Allow usage of Qt6 to be attempted" OFF) +set(QT6_LOCATION "" CACHE PATH "Additional Location to search for Qt6 libraries like C:/Qt/6.3.1/msvc2019_64/") +  option(ENABLE_QT_TRANSLATION "Enable translations for the Qt frontend" OFF)  CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_QT "Download bundled Qt binaries" "${MSVC}" "ENABLE_QT" OFF) @@ -28,6 +31,8 @@ option(YUZU_USE_BUNDLED_LIBUSB "Compile bundled libusb" OFF)  option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}") +option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF) +  option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)  option(ENABLE_CUBEB "Enables the cubeb audio backend" ON) @@ -213,128 +218,166 @@ if (MINGW)      find_library(MSWSOCK_LIBRARY mswsock REQUIRED)  endif() +# Please consider this as a stub +if(ENABLE_QT6 AND Qt6_LOCATION) +    list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}") +endif() + +function(set_yuzu_qt_components) +    # Best practice is to ask for all components at once, so they are from the same version +    set(YUZU_QT_COMPONENTS2 Core Widgets Concurrent) +    if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") +        list(APPEND YUZU_QT_COMPONENTS2 DBus) +    endif() +    if (YUZU_USE_QT_MULTIMEDIA) +        list(APPEND YUZU_QT_COMPONENTS2 Multimedia) +    endif() +    if (YUZU_USE_QT_WEB_ENGINE) +        list(APPEND YUZU_QT_COMPONENTS2 WebEngineCore WebEngineWidgets) +    endif() +    if (ENABLE_QT_TRANSLATION) +        list(APPEND YUZU_QT_COMPONENTS2 LinguistTools) +    endif() +    set(YUZU_QT_COMPONENTS ${YUZU_QT_COMPONENTS2} PARENT_SCOPE) +endfunction(set_yuzu_qt_components) +  # Qt5 requires that we find components, so it doesn't fit our pretty little find package function  if(ENABLE_QT)      set(QT_VERSION 5.15) +    # These are used to specify minimum versions +    set(QT5_VERSION 5.15) +    set(QT6_VERSION 6.3.1) -    # Check for system Qt on Linux, fallback to bundled Qt -    if (UNIX AND NOT APPLE) -        if (NOT YUZU_USE_BUNDLED_QT) -            find_package(Qt5 ${QT_VERSION} COMPONENTS Widgets DBus Multimedia) -        endif() -        if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)) -            # Check for dependencies, then enable bundled Qt download - -            # Check that the system GLIBCXX version is compatible -            find_program(OBJDUMP objdump) -            if ("${OBJDUMP}" STREQUAL "OBJDUMP-NOTFOUND") -                message(FATAL_ERROR "Required program `objdump` not found.") -            endif() -            find_library(LIBSTDCXX libstdc++.so.6) -            execute_process( -                COMMAND -                    ${OBJDUMP} -T ${LIBSTDCXX} -                COMMAND -                    grep GLIBCXX_3.4.28 -                COMMAND -                    sed "s/[0-9a-f]*.*  //" -                COMMAND -                    sed "s/ .*//" -                COMMAND -                    sort -u -                OUTPUT_VARIABLE -                    GLIBCXX_MET -            ) -            if (NOT GLIBCXX_MET) -                message(FATAL_ERROR "Qt too old or not found, and bundled Qt package is not \ -                    compatible with this system. Either install Qt ${QT_VERSION}, or provide the path \ -                    to Qt by setting the variable Qt5_ROOT.") +    set_yuzu_qt_components() +    if (ENABLE_QT6) +        find_package(Qt6 ${QT6_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS}) +    endif() +    if (Qt6_FOUND) +        message(STATUS "yuzu/CMakeLists.txt: Qt6Widgets_VERSION ${Qt6Widgets_VERSION}, setting QT_VERSION") +        set(QT_VERSION ${Qt6Widgets_VERSION}) +        set(QT_MAJOR_VERSION 6) +        # Qt6 sets cxx_std_17 and we need to undo that +        set_target_properties(Qt6::Platform PROPERTIES INTERFACE_COMPILE_FEATURES "") +    else() +        message(STATUS "yuzu/CMakeLists.txt: Qt6 not found/not selected, trying for Qt5") +        # When Qt6 partially found, need this set to use Qt5 when not specifying version +        set(QT_DEFAULT_MAJOR_VERSION 5) +        set(QT_MAJOR_VERSION 5) + +        set(YUZU_USE_QT_MULTIMEDIA ON) +        # Check for system Qt on Linux, fallback to bundled Qt +        if (UNIX AND NOT APPLE) +            if (NOT YUZU_USE_BUNDLED_QT) +                find_package(Qt5 ${QT5_VERSION} COMPONENTS Widgets DBus Multimedia)              endif() +            if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux" AND (NOT Qt5_FOUND OR YUZU_USE_BUNDLED_QT)) +                # Check for dependencies, then enable bundled Qt download -            # Check for headers -            find_package(PkgConfig REQUIRED) -            pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0) -            if (NOT QT_DEP_GLU_FOUND) -                message(FATAL_ERROR "Qt bundled pacakge dependency `glu` not found. \ -                    Perhaps `libglu1-mesa-dev` needs to be installed?") -            endif() -            pkg_check_modules(QT_DEP_MESA QUIET dri>=20.0.8) -            if (NOT QT_DEP_MESA_FOUND) -                message(FATAL_ERROR "Qt bundled pacakge dependency `dri` not found. \ -                    Perhaps `mesa-common-dev` needs to be installed?") -            endif() +                # Check that the system GLIBCXX version is compatible +                find_program(OBJDUMP objdump) +                if (NOT OBJDUMP) +                    message(FATAL_ERROR "Required program `objdump` not found.") +                endif() +                find_library(LIBSTDCXX libstdc++.so.6) +                execute_process( +                    COMMAND +                        ${OBJDUMP} -T ${LIBSTDCXX} +                    COMMAND +                        grep GLIBCXX_3.4.28 +                    COMMAND +                        sed "s/[0-9a-f]*.*  //" +                    COMMAND +                        sed "s/ .*//" +                    COMMAND +                        sort -u +                    OUTPUT_VARIABLE +                        GLIBCXX_MET +                ) +                if (NOT GLIBCXX_MET) +                    message(FATAL_ERROR "Qt too old or not found, and bundled Qt package is not \ +                        compatible with this system. Either install Qt ${QT_VERSION}, or provide the path \ +                        to Qt by setting the variable Qt5_ROOT.") +                endif() -            # Check for X libraries -            set(BUNDLED_QT_REQUIREMENTS -                libxcb-icccm.so.4 -                libxcb-image.so.0 -                libxcb-keysyms.so.1 -                libxcb-randr.so.0 -                libxcb-render-util.so.0 -                libxcb-render.so.0 -                libxcb-shape.so.0 -                libxcb-shm.so.0 -                libxcb-sync.so.1 -                libxcb-xfixes.so.0 -                libxcb-xinerama.so.0 -                libxcb-xkb.so.1 -                libxcb.so.1 -                libxkbcommon-x11.so.0 -                libxkbcommon.so.0 -            ) -            set(UNRESOLVED_QT_DEPS "") -            foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS}) -                find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT}) -                if ("${BUNDLED_QT_${REQUIREMENT}}" STREQUAL "BUNDLED_QT_${REQUIREMENT}-NOTFOUND") -                    set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT}) +                # Check for headers +                find_package(PkgConfig REQUIRED) +                pkg_check_modules(QT_DEP_GLU QUIET glu>=9.0.0) +                if (NOT QT_DEP_GLU_FOUND) +                    message(FATAL_ERROR "Qt bundled pacakge dependency `glu` not found. \ +                        Perhaps `libglu1-mesa-dev` needs to be installed?") +                endif() +                pkg_check_modules(QT_DEP_MESA QUIET dri>=20.0.8) +                if (NOT QT_DEP_MESA_FOUND) +                    message(FATAL_ERROR "Qt bundled pacakge dependency `dri` not found. \ +                        Perhaps `mesa-common-dev` needs to be installed?")                  endif() -                unset(BUNDLED_QT_${REQUIREMENT}) -            endforeach() -            unset(BUNDLED_QT_REQUIREMENTS) -            if (NOT "${UNRESOLVED_QT_DEPS}" STREQUAL "") -                message(FATAL_ERROR "Bundled Qt package missing required dependencies: ${UNRESOLVED_QT_DEPS}") -            endif() +                # Check for X libraries +                set(BUNDLED_QT_REQUIREMENTS +                    libxcb-icccm.so.4 +                    libxcb-image.so.0 +                    libxcb-keysyms.so.1 +                    libxcb-randr.so.0 +                    libxcb-render-util.so.0 +                    libxcb-render.so.0 +                    libxcb-shape.so.0 +                    libxcb-shm.so.0 +                    libxcb-sync.so.1 +                    libxcb-xfixes.so.0 +                    libxcb-xinerama.so.0 +                    libxcb-xkb.so.1 +                    libxcb.so.1 +                    libxkbcommon-x11.so.0 +                    libxkbcommon.so.0 +                ) +                set(UNRESOLVED_QT_DEPS "") +                foreach (REQUIREMENT ${BUNDLED_QT_REQUIREMENTS}) +                    find_library(BUNDLED_QT_${REQUIREMENT} ${REQUIREMENT}) +                    if (NOT BUNDLED_QT_${REQUIREMENT}) +                        set(UNRESOLVED_QT_DEPS ${UNRESOLVED_QT_DEPS} ${REQUIREMENT}) +                    endif() +                    unset(BUNDLED_QT_${REQUIREMENT}) +                endforeach() +                unset(BUNDLED_QT_REQUIREMENTS) + +                if (NOT "${UNRESOLVED_QT_DEPS}" STREQUAL "") +                    message(FATAL_ERROR "Bundled Qt package missing required dependencies: ${UNRESOLVED_QT_DEPS}") +                endif() -            set(YUZU_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE) -        endif() -        if (YUZU_USE_BUNDLED_QT) -            # Binary package currently does not support Qt webengine, so make sure it's disabled -            set(YUZU_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE) +                set(YUZU_USE_BUNDLED_QT ON CACHE BOOL "Download bundled Qt" FORCE) +            endif() +            if (YUZU_USE_BUNDLED_QT) +                # Binary package currently does not support Qt webengine, so make sure it's disabled +                set(YUZU_USE_QT_WEB_ENGINE OFF CACHE BOOL "Use Qt Webengine" FORCE) +            endif()          endif() -    endif() -    set(YUZU_QT_NO_CMAKE_SYSTEM_PATH) +        set(YUZU_QT_NO_CMAKE_SYSTEM_PATH) -    if(YUZU_USE_BUNDLED_QT) -        if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) -            set(QT_BUILD qt-5.15.2-msvc2019_64) -        elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64) -            set(QT_BUILD qt5_5_15_2) -        else() -            message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.") -        endif() +        if(YUZU_USE_BUNDLED_QT) +            if ((MSVC_VERSION GREATER_EQUAL 1920 AND MSVC_VERSION LESS 1940) AND ARCHITECTURE_x86_64) +                set(QT_BUILD qt-5.15.2-msvc2019_64) +            elseif ((${CMAKE_SYSTEM_NAME} STREQUAL "Linux") AND NOT MINGW AND ARCHITECTURE_x86_64) +                set(QT_BUILD qt5_5_15_2) +            else() +                message(FATAL_ERROR "No bundled Qt binaries for your toolchain. Disable YUZU_USE_BUNDLED_QT and provide your own.") +            endif() -        if (DEFINED QT_BUILD) -            download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX) -        endif() +            if (DEFINED QT_BUILD) +                download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX) +            endif() -        set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") +            set(QT_PREFIX_HINT HINTS "${QT_PREFIX}") -        set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH") -    endif() -    if (UNIX AND NOT APPLE AND YUZU_USE_BUNDLED_QT) -        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia DBus ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH}) -    else() -        find_package(Qt5 ${QT_VERSION} REQUIRED COMPONENTS Widgets Concurrent Multimedia ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH}) -    endif() -    if (YUZU_USE_QT_WEB_ENGINE) -        find_package(Qt5 REQUIRED COMPONENTS WebEngineCore WebEngineWidgets) -    endif() +            set(YUZU_QT_NO_CMAKE_SYSTEM_PATH "NO_CMAKE_SYSTEM_PATH") +            # Binary package for Qt5 has Qt Multimedia +            set(YUZU_USE_QT_MULTIMEDIA ON CACHE BOOL "Use Qt Multimedia" FORCE) +        endif() -    if (ENABLE_QT_TRANSLATION) -        find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT}) +        set_yuzu_qt_components() +        find_package(Qt5 ${QT5_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS} ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})      endif() +  endif()  # find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package diff --git a/CMakeModules/CopyYuzuQt5Deps.cmake b/CMakeModules/CopyYuzuQt5Deps.cmake index a353ddbb7..ab56de444 100644 --- a/CMakeModules/CopyYuzuQt5Deps.cmake +++ b/CMakeModules/CopyYuzuQt5Deps.cmake @@ -27,10 +27,13 @@ function(copy_yuzu_Qt5_deps target_dir)              Qt5Core$<$<CONFIG:Debug>:d>.*              Qt5Gui$<$<CONFIG:Debug>:d>.*              Qt5Widgets$<$<CONFIG:Debug>:d>.* -            Qt5Multimedia$<$<CONFIG:Debug>:d>.*              Qt5Network$<$<CONFIG:Debug>:d>.*          ) - +        if (YUZU_USE_QT_MULTIMEDIA) +            windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST} +                Qt5Multimedia$<$<CONFIG:Debug>:d>.* +            ) +        endif()          if (YUZU_USE_QT_WEB_ENGINE)              windows_copy_files(${target_dir} ${Qt5_DLL_DIR} ${DLL_DEST}                  Qt5Network$<$<CONFIG:Debug>:d>.* diff --git a/externals/CMakeLists.txt b/externals/CMakeLists.txt index d807ef65f..9740e017c 100644 --- a/externals/CMakeLists.txt +++ b/externals/CMakeLists.txt @@ -69,7 +69,6 @@ if (YUZU_USE_EXTERNAL_SDL2)      set(SDL_SHARED OFF)      add_subdirectory(SDL EXCLUDE_FROM_ALL) -    add_library(SDL2 ALIAS SDL2-static)  endif()  # ENet diff --git a/src/audio_core/CMakeLists.txt b/src/audio_core/CMakeLists.txt index 8e3a8f5a8..75416c53a 100644 --- a/src/audio_core/CMakeLists.txt +++ b/src/audio_core/CMakeLists.txt @@ -226,6 +226,10 @@ if(ENABLE_CUBEB)      target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)  endif()  if(ENABLE_SDL2) -    target_link_libraries(audio_core PRIVATE SDL2) +    if (YUZU_USE_EXTERNAL_SDL2) +        target_link_libraries(audio_core PRIVATE SDL2-static) +    else() +        target_link_libraries(audio_core PRIVATE SDL2) +    endif()      target_compile_definitions(audio_core PRIVATE HAVE_SDL2)  endif() diff --git a/src/audio_core/renderer/command/command_buffer.cpp b/src/audio_core/renderer/command/command_buffer.cpp index 2ef879ee1..8c6fe97e7 100644 --- a/src/audio_core/renderer/command/command_buffer.cpp +++ b/src/audio_core/renderer/command/command_buffer.cpp @@ -460,21 +460,23 @@ void CommandBuffer::GenerateDeviceSinkCommand(const s32 node_id, const s16 buffe      cmd.session_id = session_id; +    cmd.input_count = parameter.input_count; +    s16 max_input{0}; +    for (u32 i = 0; i < parameter.input_count; i++) { +        cmd.inputs[i] = buffer_offset + parameter.inputs[i]; +        max_input = std::max(max_input, cmd.inputs[i]); +    } +      if (state.upsampler_info != nullptr) {          const auto size_{state.upsampler_info->sample_count * parameter.input_count};          const auto size_bytes{size_ * sizeof(s32)};          const auto addr{memory_pool->Translate(state.upsampler_info->samples_pos, size_bytes)};          cmd.sample_buffer = {reinterpret_cast<s32*>(addr), -                             parameter.input_count * state.upsampler_info->sample_count}; +                             (max_input + 1) * state.upsampler_info->sample_count};      } else {          cmd.sample_buffer = samples_buffer;      } -    cmd.input_count = parameter.input_count; -    for (u32 i = 0; i < parameter.input_count; i++) { -        cmd.inputs[i] = buffer_offset + parameter.inputs[i]; -    } -      GenerateEnd<DeviceSinkCommand>(cmd);  } diff --git a/src/common/cache_management.cpp b/src/common/cache_management.cpp index 57810b76a..ed353828a 100644 --- a/src/common/cache_management.cpp +++ b/src/common/cache_management.cpp @@ -1,11 +1,10 @@  // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <cstdint>  #include <cstring> -#include "alignment.h" -#include "cache_management.h" -#include "common_types.h" +#include "common/cache_management.h"  namespace Common { diff --git a/src/common/cache_management.h b/src/common/cache_management.h index e467b87e4..038323e95 100644 --- a/src/common/cache_management.h +++ b/src/common/cache_management.h @@ -3,7 +3,7 @@  #pragma once -#include "stdlib.h" +#include <cstddef>  namespace Common { diff --git a/src/common/input.h b/src/common/input.h index cb30b7254..449e0193f 100644 --- a/src/common/input.h +++ b/src/common/input.h @@ -383,6 +383,16 @@ void RegisterFactory(const std::string& name, std::shared_ptr<Factory<InputDevic      }  } +inline void RegisterInputFactory(const std::string& name, +                                 std::shared_ptr<Factory<InputDevice>> factory) { +    RegisterFactory<InputDevice>(name, std::move(factory)); +} + +inline void RegisterOutputFactory(const std::string& name, +                                  std::shared_ptr<Factory<OutputDevice>> factory) { +    RegisterFactory<OutputDevice>(name, std::move(factory)); +} +  /**   * Unregisters an input device factory.   * @tparam InputDeviceType the type of input devices the factory can create @@ -395,6 +405,14 @@ void UnregisterFactory(const std::string& name) {      }  } +inline void UnregisterInputFactory(const std::string& name) { +    UnregisterFactory<InputDevice>(name); +} + +inline void UnregisterOutputFactory(const std::string& name) { +    UnregisterFactory<OutputDevice>(name); +} +  /**   * Create an input device from given paramters.   * @tparam InputDeviceType the type of input devices to create @@ -416,13 +434,21 @@ std::unique_ptr<InputDeviceType> CreateDeviceFromString(const std::string& param      return pair->second->Create(package);  } +inline std::unique_ptr<InputDevice> CreateInputDeviceFromString(const std::string& params) { +    return CreateDeviceFromString<InputDevice>(params); +} + +inline std::unique_ptr<OutputDevice> CreateOutputDeviceFromString(const std::string& params) { +    return CreateDeviceFromString<OutputDevice>(params); +} +  /** - * Create an input device from given paramters. + * Create an input device from given parameters.   * @tparam InputDeviceType the type of input devices to create - * @param A ParamPackage that contains all parameters for creating the device + * @param package A ParamPackage that contains all parameters for creating the device   */  template <typename InputDeviceType> -std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package) { +std::unique_ptr<InputDeviceType> CreateDevice(const ParamPackage& package) {      const std::string engine = package.Get("engine", "null");      const auto& factory_list = Impl::FactoryList<InputDeviceType>::list;      const auto pair = factory_list.find(engine); @@ -435,4 +461,12 @@ std::unique_ptr<InputDeviceType> CreateDevice(const Common::ParamPackage package      return pair->second->Create(package);  } +inline std::unique_ptr<InputDevice> CreateInputDevice(const ParamPackage& package) { +    return CreateDevice<InputDevice>(package); +} + +inline std::unique_ptr<OutputDevice> CreateOutputDevice(const ParamPackage& package) { +    return CreateDevice<OutputDevice>(package); +} +  } // namespace Common::Input diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 8173462cb..d8ffe34c3 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp @@ -48,6 +48,7 @@ void LogSettings() {      log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue());      log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue());      log_setting("Renderer_ScalingFilter", values.scaling_filter.GetValue()); +    log_setting("Renderer_FSRSlider", values.fsr_sharpening_slider.GetValue());      log_setting("Renderer_AntiAliasing", values.anti_aliasing.GetValue());      log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue());      log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); @@ -181,6 +182,7 @@ void RestoreGlobalState(bool is_powered_on) {      values.cpuopt_unsafe_ignore_global_monitor.SetGlobal(true);      // Renderer +    values.fsr_sharpening_slider.SetGlobal(true);      values.renderer_backend.SetGlobal(true);      values.vulkan_device.SetGlobal(true);      values.aspect_ratio.SetGlobal(true); diff --git a/src/common/settings.h b/src/common/settings.h index 0eb98939c..00e4421f7 100644 --- a/src/common/settings.h +++ b/src/common/settings.h @@ -421,6 +421,7 @@ struct Values {      ResolutionScalingInfo resolution_info{};      SwitchableSetting<ResolutionSetup> resolution_setup{ResolutionSetup::Res1X, "resolution_setup"};      SwitchableSetting<ScalingFilter> scaling_filter{ScalingFilter::Bilinear, "scaling_filter"}; +    SwitchableSetting<int, true> fsr_sharpening_slider{25, 0, 200, "fsr_sharpening_slider"};      SwitchableSetting<AntiAliasing> anti_aliasing{AntiAliasing::None, "anti_aliasing"};      // *nix platforms may have issues with the borderless windowed fullscreen mode.      // Default to exclusive fullscreen on these platforms for now. @@ -442,7 +443,7 @@ struct Values {      SwitchableSetting<NvdecEmulation> nvdec_emulation{NvdecEmulation::GPU, "nvdec_emulation"};      SwitchableSetting<bool> accelerate_astc{true, "accelerate_astc"};      SwitchableSetting<bool> use_vsync{true, "use_vsync"}; -    SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLASM, ShaderBackend::GLSL, +    SwitchableSetting<ShaderBackend, true> shader_backend{ShaderBackend::GLSL, ShaderBackend::GLSL,                                                            ShaderBackend::SPIRV, "shader_backend"};      SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"};      SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; diff --git a/src/core/crypto/key_manager.cpp b/src/core/crypto/key_manager.cpp index 443323390..65a9fe802 100644 --- a/src/core/crypto/key_manager.cpp +++ b/src/core/crypto/key_manager.cpp @@ -578,18 +578,18 @@ KeyManager::KeyManager() {      if (Settings::values.use_dev_keys) {          dev_mode = true; -        LoadFromFile(yuzu_keys_dir / "dev.keys", false);          LoadFromFile(yuzu_keys_dir / "dev.keys_autogenerated", false); +        LoadFromFile(yuzu_keys_dir / "dev.keys", false);      } else {          dev_mode = false; -        LoadFromFile(yuzu_keys_dir / "prod.keys", false);          LoadFromFile(yuzu_keys_dir / "prod.keys_autogenerated", false); +        LoadFromFile(yuzu_keys_dir / "prod.keys", false);      } -    LoadFromFile(yuzu_keys_dir / "title.keys", true);      LoadFromFile(yuzu_keys_dir / "title.keys_autogenerated", true); -    LoadFromFile(yuzu_keys_dir / "console.keys", false); +    LoadFromFile(yuzu_keys_dir / "title.keys", true);      LoadFromFile(yuzu_keys_dir / "console.keys_autogenerated", false); +    LoadFromFile(yuzu_keys_dir / "console.keys", false);  }  static bool ValidCryptoRevisionString(std::string_view base, size_t begin, size_t length) { diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp index fb7e5802a..b6c8cc58d 100644 --- a/src/core/hid/emulated_console.cpp +++ b/src/core/hid/emulated_console.cpp @@ -68,7 +68,7 @@ void EmulatedConsole::ReloadInput() {      // If you load any device here add the equivalent to the UnloadInput() function      SetTouchParams(); -    motion_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(motion_params); +    motion_devices = Common::Input::CreateInputDevice(motion_params);      if (motion_devices) {          motion_devices->SetCallback({              .on_change = @@ -79,7 +79,7 @@ void EmulatedConsole::ReloadInput() {      // Unique index for identifying touch device source      std::size_t index = 0;      for (auto& touch_device : touch_devices) { -        touch_device = Common::Input::CreateDevice<Common::Input::InputDevice>(touch_params[index]); +        touch_device = Common::Input::CreateInputDevice(touch_params[index]);          if (!touch_device) {              continue;          } diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index ec1364452..c96d9eef3 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp @@ -1,6 +1,8 @@  // SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project  // SPDX-License-Identifier: GPL-2.0-or-later +#include <algorithm> +  #include "common/thread.h"  #include "core/hid/emulated_controller.h"  #include "core/hid/input_converter.h" @@ -144,29 +146,23 @@ void EmulatedController::LoadDevices() {      LoadTASParams(); -    std::transform(button_params.begin() + Settings::NativeButton::BUTTON_HID_BEGIN, -                   button_params.begin() + Settings::NativeButton::BUTTON_NS_END, -                   button_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); -    std::transform(stick_params.begin() + Settings::NativeAnalog::STICK_HID_BEGIN, -                   stick_params.begin() + Settings::NativeAnalog::STICK_HID_END, -                   stick_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); -    std::transform(motion_params.begin() + Settings::NativeMotion::MOTION_HID_BEGIN, -                   motion_params.begin() + Settings::NativeMotion::MOTION_HID_END, -                   motion_devices.begin(), Common::Input::CreateDevice<Common::Input::InputDevice>); -    std::transform(trigger_params.begin(), trigger_params.end(), trigger_devices.begin(), -                   Common::Input::CreateDevice<Common::Input::InputDevice>); -    std::transform(battery_params.begin(), battery_params.end(), battery_devices.begin(), -                   Common::Input::CreateDevice<Common::Input::InputDevice>); -    camera_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(camera_params); -    nfc_devices = Common::Input::CreateDevice<Common::Input::InputDevice>(nfc_params); -    std::transform(output_params.begin(), output_params.end(), output_devices.begin(), -                   Common::Input::CreateDevice<Common::Input::OutputDevice>); +    std::ranges::transform(button_params, button_devices.begin(), Common::Input::CreateInputDevice); +    std::ranges::transform(stick_params, stick_devices.begin(), Common::Input::CreateInputDevice); +    std::ranges::transform(motion_params, motion_devices.begin(), Common::Input::CreateInputDevice); +    std::ranges::transform(trigger_params, trigger_devices.begin(), +                           Common::Input::CreateInputDevice); +    std::ranges::transform(battery_params, battery_devices.begin(), +                           Common::Input::CreateInputDevice); +    camera_devices = Common::Input::CreateInputDevice(camera_params); +    nfc_devices = Common::Input::CreateInputDevice(nfc_params); +    std::ranges::transform(output_params, output_devices.begin(), +                           Common::Input::CreateOutputDevice);      // Initialize TAS devices -    std::transform(tas_button_params.begin(), tas_button_params.end(), tas_button_devices.begin(), -                   Common::Input::CreateDevice<Common::Input::InputDevice>); -    std::transform(tas_stick_params.begin(), tas_stick_params.end(), tas_stick_devices.begin(), -                   Common::Input::CreateDevice<Common::Input::InputDevice>); +    std::ranges::transform(tas_button_params, tas_button_devices.begin(), +                           Common::Input::CreateInputDevice); +    std::ranges::transform(tas_stick_params, tas_stick_devices.begin(), +                           Common::Input::CreateInputDevice);  }  void EmulatedController::LoadTASParams() { diff --git a/src/core/hid/emulated_devices.cpp b/src/core/hid/emulated_devices.cpp index 8d367b546..e421828d2 100644 --- a/src/core/hid/emulated_devices.cpp +++ b/src/core/hid/emulated_devices.cpp @@ -25,12 +25,12 @@ void EmulatedDevices::ReloadInput() {          Common::ParamPackage mouse_params;          mouse_params.Set("engine", "mouse");          mouse_params.Set("button", static_cast<int>(key_index)); -        mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params); +        mouse_device = Common::Input::CreateInputDevice(mouse_params);          key_index++;      } -    mouse_stick_device = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        "engine:mouse,axis_x:0,axis_y:1"); +    mouse_stick_device = +        Common::Input::CreateInputDeviceFromString("engine:mouse,axis_x:0,axis_y:1");      // First two axis are reserved for mouse position      key_index = 2; @@ -38,7 +38,7 @@ void EmulatedDevices::ReloadInput() {          Common::ParamPackage mouse_params;          mouse_params.Set("engine", "mouse");          mouse_params.Set("axis", static_cast<int>(key_index)); -        mouse_device = Common::Input::CreateDevice<Common::Input::InputDevice>(mouse_params); +        mouse_device = Common::Input::CreateInputDevice(mouse_params);          key_index++;      } @@ -50,7 +50,7 @@ void EmulatedDevices::ReloadInput() {          keyboard_params.Set("button", static_cast<int>(key_index));          keyboard_params.Set("port", 1);          keyboard_params.Set("pad", 0); -        keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params); +        keyboard_device = Common::Input::CreateInputDevice(keyboard_params);          key_index++;      } @@ -62,11 +62,11 @@ void EmulatedDevices::ReloadInput() {          keyboard_params.Set("button", static_cast<int>(key_index));          keyboard_params.Set("port", 1);          keyboard_params.Set("pad", 1); -        keyboard_device = Common::Input::CreateDevice<Common::Input::InputDevice>(keyboard_params); +        keyboard_device = Common::Input::CreateInputDevice(keyboard_params);          key_index++;      } -    ring_analog_device = Common::Input::CreateDevice<Common::Input::InputDevice>(ring_params); +    ring_analog_device = Common::Input::CreateInputDevice(ring_params);      for (std::size_t index = 0; index < mouse_button_devices.size(); ++index) {          if (!mouse_button_devices[index]) { @@ -145,6 +145,7 @@ void EmulatedDevices::UnloadInput() {      for (auto& button : keyboard_modifier_devices) {          button.reset();      } +    ring_analog_device.reset();  }  void EmulatedDevices::EnableConfiguration() { diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp index eda2041a0..aba51d280 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.cpp @@ -28,13 +28,15 @@ SyncpointManager::SyncpointManager(Tegra::Host1x::Host1x& host1x_) : host1x{host  SyncpointManager::~SyncpointManager() = default;  u32 SyncpointManager::ReserveSyncpoint(u32 id, bool client_managed) { -    if (syncpoints.at(id).reserved) { +    auto& syncpoint = syncpoints.at(id); + +    if (syncpoint.reserved) {          ASSERT_MSG(false, "Requested syncpoint is in use");          return 0;      } -    syncpoints.at(id).reserved = true; -    syncpoints.at(id).interface_managed = client_managed; +    syncpoint.reserved = true; +    syncpoint.interface_managed = client_managed;      return id;  } @@ -56,11 +58,12 @@ u32 SyncpointManager::AllocateSyncpoint(bool client_managed) {  void SyncpointManager::FreeSyncpoint(u32 id) {      std::lock_guard lock(reservation_lock); -    ASSERT(syncpoints.at(id).reserved); -    syncpoints.at(id).reserved = false; +    auto& syncpoint = syncpoints.at(id); +    ASSERT(syncpoint.reserved); +    syncpoint.reserved = false;  } -bool SyncpointManager::IsSyncpointAllocated(u32 id) { +bool SyncpointManager::IsSyncpointAllocated(u32 id) const {      return (id <= SyncpointCount) && syncpoints[id].reserved;  } @@ -69,7 +72,7 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const {      if (!syncpoint.reserved) {          ASSERT(false); -        return 0; +        return false;      }      // If the interface manages counters then we don't keep track of the maximum value as it handles @@ -82,40 +85,51 @@ bool SyncpointManager::HasSyncpointExpired(u32 id, u32 threshold) const {  }  u32 SyncpointManager::IncrementSyncpointMaxExt(u32 id, u32 amount) { -    if (!syncpoints.at(id).reserved) { +    auto& syncpoint = syncpoints.at(id); + +    if (!syncpoint.reserved) {          ASSERT(false);          return 0;      } -    return syncpoints.at(id).counter_max += amount; +    return syncpoint.counter_max += amount;  }  u32 SyncpointManager::ReadSyncpointMinValue(u32 id) { -    if (!syncpoints.at(id).reserved) { +    auto& syncpoint = syncpoints.at(id); + +    if (!syncpoint.reserved) {          ASSERT(false);          return 0;      } -    return syncpoints.at(id).counter_min; +    return syncpoint.counter_min;  }  u32 SyncpointManager::UpdateMin(u32 id) { -    if (!syncpoints.at(id).reserved) { +    auto& syncpoint = syncpoints.at(id); + +    if (!syncpoint.reserved) {          ASSERT(false);          return 0;      } -    syncpoints.at(id).counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id); -    return syncpoints.at(id).counter_min; +    syncpoint.counter_min = host1x.GetSyncpointManager().GetHostSyncpointValue(id); +    return syncpoint.counter_min;  }  NvFence SyncpointManager::GetSyncpointFence(u32 id) { -    if (!syncpoints.at(id).reserved) { +    auto& syncpoint = syncpoints.at(id); + +    if (!syncpoint.reserved) {          ASSERT(false);          return NvFence{};      } -    return {.id = static_cast<s32>(id), .value = syncpoints.at(id).counter_max}; +    return { +        .id = static_cast<s32>(id), +        .value = syncpoint.counter_max, +    };  }  } // namespace Service::Nvidia::NvCore diff --git a/src/core/hle/service/nvdrv/core/syncpoint_manager.h b/src/core/hle/service/nvdrv/core/syncpoint_manager.h index b76ef9032..4f2cefae5 100644 --- a/src/core/hle/service/nvdrv/core/syncpoint_manager.h +++ b/src/core/hle/service/nvdrv/core/syncpoint_manager.h @@ -44,7 +44,7 @@ public:      /**       * @brief Checks if the given syncpoint is both allocated and below the number of HW syncpoints       */ -    bool IsSyncpointAllocated(u32 id); +    bool IsSyncpointAllocated(u32 id) const;      /**       * @brief Finds a free syncpoint and reserves it diff --git a/src/core/hle/service/nvdrv/nvdrv.cpp b/src/core/hle/service/nvdrv/nvdrv.cpp index 9f4c7c99a..6fc8565c0 100644 --- a/src/core/hle/service/nvdrv/nvdrv.cpp +++ b/src/core/hle/service/nvdrv/nvdrv.cpp @@ -55,48 +55,40 @@ void InstallInterfaces(SM::ServiceManager& service_manager, NVFlinger::NVFlinger  Module::Module(Core::System& system)      : container{system.Host1x()}, service_context{system, "nvdrv"}, events_interface{*this} {      builders["/dev/nvhost-as-gpu"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_as_gpu>(system, *this, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_as_gpu>(system, *this, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-gpu"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_gpu>(system, events_interface, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_gpu>(system, events_interface, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-ctrl-gpu"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_ctrl_gpu>(system, events_interface); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvmap"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvmap>(system, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvmap>(system, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvdisp_disp0"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvdisp_disp0>(system, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvdisp_disp0>(system, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-ctrl"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_ctrl>(system, events_interface, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-nvdec"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_nvdec>(system, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_nvdec>(system, container); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-nvjpg"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = std::make_shared<Devices::nvhost_nvjpg>(system); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_nvjpg>(system); +        return open_files.emplace(fd, std::move(device)).first;      };      builders["/dev/nvhost-vic"] = [this, &system](DeviceFD fd) { -        std::shared_ptr<Devices::nvdevice> device = -            std::make_shared<Devices::nvhost_vic>(system, container); -        return open_files.emplace(fd, device).first; +        auto device = std::make_shared<Devices::nvhost_vic>(system, container); +        return open_files.emplace(fd, std::move(device)).first;      };  } diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp index 6d2c92a2c..152bb5bdf 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_item_consumer.cpp @@ -39,7 +39,7 @@ Status BufferItemConsumer::AcquireBuffer(BufferItem* item, std::chrono::nanoseco      return Status::NoError;  } -Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, Fence& release_fence) { +Status BufferItemConsumer::ReleaseBuffer(const BufferItem& item, const Fence& release_fence) {      std::scoped_lock lock{mutex};      if (const auto status = AddReleaseFenceLocked(item.buf, item.graphic_buffer, release_fence); diff --git a/src/core/hle/service/nvflinger/buffer_item_consumer.h b/src/core/hle/service/nvflinger/buffer_item_consumer.h index 69046233d..a5c655d9e 100644 --- a/src/core/hle/service/nvflinger/buffer_item_consumer.h +++ b/src/core/hle/service/nvflinger/buffer_item_consumer.h @@ -22,7 +22,7 @@ public:      explicit BufferItemConsumer(std::unique_ptr<BufferQueueConsumer> consumer);      Status AcquireBuffer(BufferItem* item, std::chrono::nanoseconds present_when,                           bool wait_for_fence = true); -    Status ReleaseBuffer(const BufferItem& item, Fence& release_fence); +    Status ReleaseBuffer(const BufferItem& item, const Fence& release_fence);  };  } // namespace Service::android diff --git a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp index 1ce67c771..0767e548d 100644 --- a/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp +++ b/src/core/hle/service/nvflinger/buffer_queue_consumer.cpp @@ -169,7 +169,7 @@ Status BufferQueueConsumer::Connect(std::shared_ptr<IConsumerListener> consumer_          return Status::NoInit;      } -    core->consumer_listener = consumer_listener; +    core->consumer_listener = std::move(consumer_listener);      core->consumer_controlled_by_app = controlled_by_app;      return Status::NoError; diff --git a/src/core/hle/service/nvflinger/consumer_base.cpp b/src/core/hle/service/nvflinger/consumer_base.cpp index 5b9995854..982531e2d 100644 --- a/src/core/hle/service/nvflinger/consumer_base.cpp +++ b/src/core/hle/service/nvflinger/consumer_base.cpp @@ -83,7 +83,7 @@ Status ConsumerBase::AcquireBufferLocked(BufferItem* item, std::chrono::nanoseco  }  Status ConsumerBase::AddReleaseFenceLocked(s32 slot, -                                           const std::shared_ptr<GraphicBuffer> graphic_buffer, +                                           const std::shared_ptr<GraphicBuffer>& graphic_buffer,                                             const Fence& fence) {      LOG_DEBUG(Service_NVFlinger, "slot={}", slot); @@ -100,7 +100,7 @@ Status ConsumerBase::AddReleaseFenceLocked(s32 slot,  }  Status ConsumerBase::ReleaseBufferLocked(s32 slot, -                                         const std::shared_ptr<GraphicBuffer> graphic_buffer) { +                                         const std::shared_ptr<GraphicBuffer>& graphic_buffer) {      // If consumer no longer tracks this graphic_buffer (we received a new      // buffer on the same slot), the buffer producer is definitely no longer      // tracking it. @@ -121,7 +121,7 @@ Status ConsumerBase::ReleaseBufferLocked(s32 slot,  }  bool ConsumerBase::StillTracking(s32 slot, -                                 const std::shared_ptr<GraphicBuffer> graphic_buffer) const { +                                 const std::shared_ptr<GraphicBuffer>& graphic_buffer) const {      if (slot < 0 || slot >= BufferQueueDefs::NUM_BUFFER_SLOTS) {          return false;      } diff --git a/src/core/hle/service/nvflinger/consumer_base.h b/src/core/hle/service/nvflinger/consumer_base.h index 90ba07f45..9a8a5f6bb 100644 --- a/src/core/hle/service/nvflinger/consumer_base.h +++ b/src/core/hle/service/nvflinger/consumer_base.h @@ -27,18 +27,18 @@ public:  protected:      explicit ConsumerBase(std::unique_ptr<BufferQueueConsumer> consumer_); -    virtual ~ConsumerBase(); +    ~ConsumerBase() override; -    virtual void OnFrameAvailable(const BufferItem& item) override; -    virtual void OnFrameReplaced(const BufferItem& item) override; -    virtual void OnBuffersReleased() override; -    virtual void OnSidebandStreamChanged() override; +    void OnFrameAvailable(const BufferItem& item) override; +    void OnFrameReplaced(const BufferItem& item) override; +    void OnBuffersReleased() override; +    void OnSidebandStreamChanged() override;      void FreeBufferLocked(s32 slot_index);      Status AcquireBufferLocked(BufferItem* item, std::chrono::nanoseconds present_when); -    Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer); -    bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer) const; -    Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer> graphic_buffer, +    Status ReleaseBufferLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer); +    bool StillTracking(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer) const; +    Status AddReleaseFenceLocked(s32 slot, const std::shared_ptr<GraphicBuffer>& graphic_buffer,                                   const Fence& fence);      struct Slot final { diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp index c3af12c90..d1cbadde4 100644 --- a/src/core/hle/service/nvflinger/nvflinger.cpp +++ b/src/core/hle/service/nvflinger/nvflinger.cpp @@ -307,8 +307,7 @@ void NVFlinger::Compose() {          swap_interval = buffer.swap_interval; -        auto fence = android::Fence::NoFence(); -        layer.GetConsumer().ReleaseBuffer(buffer, fence); +        layer.GetConsumer().ReleaseBuffer(buffer, android::Fence::NoFence());      }  } diff --git a/src/core/hle/service/nvflinger/producer_listener.h b/src/core/hle/service/nvflinger/producer_listener.h index 1c4d5db0e..6bf8aaf1e 100644 --- a/src/core/hle/service/nvflinger/producer_listener.h +++ b/src/core/hle/service/nvflinger/producer_listener.h @@ -10,6 +10,7 @@ namespace Service::android {  class IProducerListener {  public: +    virtual ~IProducerListener() = default;      virtual void OnBufferReleased() = 0;  }; diff --git a/src/input_common/CMakeLists.txt b/src/input_common/CMakeLists.txt index cc6f0ffc0..193127d0a 100644 --- a/src/input_common/CMakeLists.txt +++ b/src/input_common/CMakeLists.txt @@ -55,7 +55,11 @@ if (ENABLE_SDL2)          drivers/sdl_driver.cpp          drivers/sdl_driver.h      ) -    target_link_libraries(input_common PRIVATE SDL2) +    if (YUZU_USE_EXTERNAL_SDL2) +        target_link_libraries(input_common PRIVATE SDL2-static) +    else() +        target_link_libraries(input_common PRIVATE SDL2) +    endif()      target_compile_definitions(input_common PRIVATE HAVE_SDL2)  endif() diff --git a/src/input_common/drivers/sdl_driver.cpp b/src/input_common/drivers/sdl_driver.cpp index 45ce588f0..8de86b61e 100644 --- a/src/input_common/drivers/sdl_driver.cpp +++ b/src/input_common/drivers/sdl_driver.cpp @@ -361,6 +361,12 @@ void SDLDriver::CloseJoystick(SDL_Joystick* sdl_joystick) {      }  } +void SDLDriver::PumpEvents() const { +    if (initialized) { +        SDL_PumpEvents(); +    } +} +  void SDLDriver::HandleGameControllerEvent(const SDL_Event& event) {      switch (event.type) {      case SDL_JOYBUTTONUP: { @@ -451,14 +457,6 @@ SDLDriver::SDLDriver(std::string input_engine_) : InputEngine(std::move(input_en      initialized = true;      if (start_thread) { -        poll_thread = std::thread([this] { -            Common::SetCurrentThreadName("SDL_MainLoop"); -            using namespace std::chrono_literals; -            while (initialized) { -                SDL_PumpEvents(); -                std::this_thread::sleep_for(1ms); -            } -        });          vibration_thread = std::thread([this] {              Common::SetCurrentThreadName("SDL_Vibration");              using namespace std::chrono_literals; @@ -481,7 +479,6 @@ SDLDriver::~SDLDriver() {      initialized = false;      if (start_thread) { -        poll_thread.join();          vibration_thread.join();          SDL_QuitSubSystem(SDL_INIT_JOYSTICK | SDL_INIT_GAMECONTROLLER);      } diff --git a/src/input_common/drivers/sdl_driver.h b/src/input_common/drivers/sdl_driver.h index d1b4471cf..366bcc496 100644 --- a/src/input_common/drivers/sdl_driver.h +++ b/src/input_common/drivers/sdl_driver.h @@ -36,6 +36,8 @@ public:      /// Unregisters SDL device factories and shut them down.      ~SDLDriver() override; +    void PumpEvents() const; +      /// Handle SDL_Events for joysticks from SDL_PollEvent      void HandleGameControllerEvent(const SDL_Event& event); @@ -128,7 +130,6 @@ private:      bool start_thread = false;      std::atomic<bool> initialized = false; -    std::thread poll_thread;      std::thread vibration_thread;  };  } // namespace InputCommon diff --git a/src/input_common/helpers/stick_from_buttons.cpp b/src/input_common/helpers/stick_from_buttons.cpp index 536d413a5..82aa6ac2f 100644 --- a/src/input_common/helpers/stick_from_buttons.cpp +++ b/src/input_common/helpers/stick_from_buttons.cpp @@ -294,6 +294,15 @@ public:      }  private: +    static constexpr Common::Input::AnalogProperties properties{ +        .deadzone = 0.0f, +        .range = 1.0f, +        .threshold = 0.5f, +        .offset = 0.0f, +        .inverted = false, +        .toggle = false, +    }; +      Button up;      Button down;      Button left; @@ -311,23 +320,17 @@ private:      float last_x_axis_value{};      float last_y_axis_value{};      Common::Input::ButtonStatus modifier_status{}; -    const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};      std::chrono::time_point<std::chrono::steady_clock> last_update;  };  std::unique_ptr<Common::Input::InputDevice> StickFromButton::Create(      const Common::ParamPackage& params) {      const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); -    auto up = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("up", null_engine)); -    auto down = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("down", null_engine)); -    auto left = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("left", null_engine)); -    auto right = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("right", null_engine)); -    auto modifier = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("modifier", null_engine)); +    auto up = Common::Input::CreateInputDeviceFromString(params.Get("up", null_engine)); +    auto down = Common::Input::CreateInputDeviceFromString(params.Get("down", null_engine)); +    auto left = Common::Input::CreateInputDeviceFromString(params.Get("left", null_engine)); +    auto right = Common::Input::CreateInputDeviceFromString(params.Get("right", null_engine)); +    auto modifier = Common::Input::CreateInputDeviceFromString(params.Get("modifier", null_engine));      auto modifier_scale = params.Get("modifier_scale", 0.5f);      auto modifier_angle = params.Get("modifier_angle", 5.5f);      return std::make_unique<Stick>(std::move(up), std::move(down), std::move(left), diff --git a/src/input_common/helpers/touch_from_buttons.cpp b/src/input_common/helpers/touch_from_buttons.cpp index 003a38da5..e064b13d9 100644 --- a/src/input_common/helpers/touch_from_buttons.cpp +++ b/src/input_common/helpers/touch_from_buttons.cpp @@ -59,18 +59,25 @@ public:      }  private: +    static constexpr Common::Input::AnalogProperties properties{ +        .deadzone = 0.0f, +        .range = 1.0f, +        .threshold = 0.5f, +        .offset = 0.0f, +        .inverted = false, +        .toggle = false, +    }; +      Button button;      bool last_button_value;      const float x;      const float y; -    const Common::Input::AnalogProperties properties{0.0f, 1.0f, 0.5f, 0.0f, false};  };  std::unique_ptr<Common::Input::InputDevice> TouchFromButton::Create(      const Common::ParamPackage& params) {      const std::string null_engine = Common::ParamPackage{{"engine", "null"}}.Serialize(); -    auto button = Common::Input::CreateDeviceFromString<Common::Input::InputDevice>( -        params.Get("button", null_engine)); +    auto button = Common::Input::CreateInputDeviceFromString(params.Get("button", null_engine));      const float x = params.Get("x", 0.0f) / 1280.0f;      const float y = params.Get("y", 0.0f) / 720.0f;      return std::make_unique<TouchFromButtonDevice>(std::move(button), x, y); diff --git a/src/input_common/main.cpp b/src/input_common/main.cpp index b2064ef95..942a13535 100644 --- a/src/input_common/main.cpp +++ b/src/input_common/main.cpp @@ -33,119 +33,113 @@ struct InputSubsystem::Impl {          keyboard->SetMappingCallback(mapping_callback);          keyboard_factory = std::make_shared<InputFactory>(keyboard);          keyboard_output_factory = std::make_shared<OutputFactory>(keyboard); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName(), -                                                                   keyboard_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName(), -                                                                    keyboard_output_factory); +        Common::Input::RegisterInputFactory(keyboard->GetEngineName(), keyboard_factory); +        Common::Input::RegisterOutputFactory(keyboard->GetEngineName(), keyboard_output_factory);          mouse = std::make_shared<Mouse>("mouse");          mouse->SetMappingCallback(mapping_callback);          mouse_factory = std::make_shared<InputFactory>(mouse);          mouse_output_factory = std::make_shared<OutputFactory>(mouse); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(mouse->GetEngineName(), -                                                                   mouse_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName(), -                                                                    mouse_output_factory); +        Common::Input::RegisterInputFactory(mouse->GetEngineName(), mouse_factory); +        Common::Input::RegisterOutputFactory(mouse->GetEngineName(), mouse_output_factory);          touch_screen = std::make_shared<TouchScreen>("touch");          touch_screen_factory = std::make_shared<InputFactory>(touch_screen); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName(), -                                                                   touch_screen_factory); +        Common::Input::RegisterInputFactory(touch_screen->GetEngineName(), touch_screen_factory);          gcadapter = std::make_shared<GCAdapter>("gcpad");          gcadapter->SetMappingCallback(mapping_callback);          gcadapter_input_factory = std::make_shared<InputFactory>(gcadapter);          gcadapter_output_factory = std::make_shared<OutputFactory>(gcadapter); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName(), -                                                                   gcadapter_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName(), -                                                                    gcadapter_output_factory); +        Common::Input::RegisterInputFactory(gcadapter->GetEngineName(), gcadapter_input_factory); +        Common::Input::RegisterOutputFactory(gcadapter->GetEngineName(), gcadapter_output_factory);          udp_client = std::make_shared<CemuhookUDP::UDPClient>("cemuhookudp");          udp_client->SetMappingCallback(mapping_callback);          udp_client_input_factory = std::make_shared<InputFactory>(udp_client);          udp_client_output_factory = std::make_shared<OutputFactory>(udp_client); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName(), -                                                                   udp_client_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName(), -                                                                    udp_client_output_factory); +        Common::Input::RegisterInputFactory(udp_client->GetEngineName(), udp_client_input_factory); +        Common::Input::RegisterOutputFactory(udp_client->GetEngineName(), +                                             udp_client_output_factory);          tas_input = std::make_shared<TasInput::Tas>("tas");          tas_input->SetMappingCallback(mapping_callback);          tas_input_factory = std::make_shared<InputFactory>(tas_input);          tas_output_factory = std::make_shared<OutputFactory>(tas_input); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName(), -                                                                   tas_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName(), -                                                                    tas_output_factory); +        Common::Input::RegisterInputFactory(tas_input->GetEngineName(), tas_input_factory); +        Common::Input::RegisterOutputFactory(tas_input->GetEngineName(), tas_output_factory);          camera = std::make_shared<Camera>("camera");          camera->SetMappingCallback(mapping_callback);          camera_input_factory = std::make_shared<InputFactory>(camera);          camera_output_factory = std::make_shared<OutputFactory>(camera); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(camera->GetEngineName(), -                                                                   camera_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(camera->GetEngineName(), -                                                                    camera_output_factory); +        Common::Input::RegisterInputFactory(camera->GetEngineName(), camera_input_factory); +        Common::Input::RegisterOutputFactory(camera->GetEngineName(), camera_output_factory);          virtual_amiibo = std::make_shared<VirtualAmiibo>("virtual_amiibo");          virtual_amiibo->SetMappingCallback(mapping_callback);          virtual_amiibo_input_factory = std::make_shared<InputFactory>(virtual_amiibo);          virtual_amiibo_output_factory = std::make_shared<OutputFactory>(virtual_amiibo); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(virtual_amiibo->GetEngineName(), -                                                                   virtual_amiibo_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(virtual_amiibo->GetEngineName(), -                                                                    virtual_amiibo_output_factory); +        Common::Input::RegisterInputFactory(virtual_amiibo->GetEngineName(), +                                            virtual_amiibo_input_factory); +        Common::Input::RegisterOutputFactory(virtual_amiibo->GetEngineName(), +                                             virtual_amiibo_output_factory);  #ifdef HAVE_SDL2          sdl = std::make_shared<SDLDriver>("sdl");          sdl->SetMappingCallback(mapping_callback);          sdl_input_factory = std::make_shared<InputFactory>(sdl);          sdl_output_factory = std::make_shared<OutputFactory>(sdl); -        Common::Input::RegisterFactory<Common::Input::InputDevice>(sdl->GetEngineName(), -                                                                   sdl_input_factory); -        Common::Input::RegisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName(), -                                                                    sdl_output_factory); +        Common::Input::RegisterInputFactory(sdl->GetEngineName(), sdl_input_factory); +        Common::Input::RegisterOutputFactory(sdl->GetEngineName(), sdl_output_factory);  #endif -        Common::Input::RegisterFactory<Common::Input::InputDevice>( -            "touch_from_button", std::make_shared<TouchFromButton>()); -        Common::Input::RegisterFactory<Common::Input::InputDevice>( -            "analog_from_button", std::make_shared<StickFromButton>()); +        Common::Input::RegisterInputFactory("touch_from_button", +                                            std::make_shared<TouchFromButton>()); +        Common::Input::RegisterInputFactory("analog_from_button", +                                            std::make_shared<StickFromButton>());      }      void Shutdown() { -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(keyboard->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(keyboard->GetEngineName()); +        Common::Input::UnregisterInputFactory(keyboard->GetEngineName()); +        Common::Input::UnregisterOutputFactory(keyboard->GetEngineName());          keyboard.reset(); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(mouse->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(mouse->GetEngineName()); +        Common::Input::UnregisterInputFactory(mouse->GetEngineName()); +        Common::Input::UnregisterOutputFactory(mouse->GetEngineName());          mouse.reset(); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(touch_screen->GetEngineName()); +        Common::Input::UnregisterInputFactory(touch_screen->GetEngineName());          touch_screen.reset(); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(gcadapter->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(gcadapter->GetEngineName()); +        Common::Input::UnregisterInputFactory(gcadapter->GetEngineName()); +        Common::Input::UnregisterOutputFactory(gcadapter->GetEngineName());          gcadapter.reset(); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(udp_client->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(udp_client->GetEngineName()); +        Common::Input::UnregisterInputFactory(udp_client->GetEngineName()); +        Common::Input::UnregisterOutputFactory(udp_client->GetEngineName());          udp_client.reset(); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(tas_input->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(tas_input->GetEngineName()); +        Common::Input::UnregisterInputFactory(tas_input->GetEngineName()); +        Common::Input::UnregisterOutputFactory(tas_input->GetEngineName());          tas_input.reset(); +        Common::Input::UnregisterInputFactory(camera->GetEngineName()); +        Common::Input::UnregisterOutputFactory(camera->GetEngineName()); +        camera.reset(); + +        Common::Input::UnregisterInputFactory(virtual_amiibo->GetEngineName()); +        Common::Input::UnregisterOutputFactory(virtual_amiibo->GetEngineName()); +        virtual_amiibo.reset(); +  #ifdef HAVE_SDL2 -        Common::Input::UnregisterFactory<Common::Input::InputDevice>(sdl->GetEngineName()); -        Common::Input::UnregisterFactory<Common::Input::OutputDevice>(sdl->GetEngineName()); +        Common::Input::UnregisterInputFactory(sdl->GetEngineName()); +        Common::Input::UnregisterOutputFactory(sdl->GetEngineName());          sdl.reset();  #endif -        Common::Input::UnregisterFactory<Common::Input::InputDevice>("touch_from_button"); -        Common::Input::UnregisterFactory<Common::Input::InputDevice>("analog_from_button"); +        Common::Input::UnregisterInputFactory("touch_from_button"); +        Common::Input::UnregisterInputFactory("analog_from_button");      }      [[nodiscard]] std::vector<Common::ParamPackage> GetInputDevices() const { @@ -324,6 +318,12 @@ struct InputSubsystem::Impl {  #endif      } +    void PumpEvents() const { +#ifdef HAVE_SDL2 +        sdl->PumpEvents(); +#endif +    } +      void RegisterInput(const MappingData& data) {          mapping_factory->RegisterInput(data);      } @@ -472,6 +472,10 @@ void InputSubsystem::StopMapping() const {      impl->mapping_factory->StopMapping();  } +void InputSubsystem::PumpEvents() const { +    impl->PumpEvents(); +} +  std::string GenerateKeyboardParam(int key_code) {      Common::ParamPackage param;      param.Set("engine", "keyboard"); diff --git a/src/input_common/main.h b/src/input_common/main.h index ced252383..6218c37f6 100644 --- a/src/input_common/main.h +++ b/src/input_common/main.h @@ -147,6 +147,9 @@ public:      /// Stop polling from all backends.      void StopMapping() const; +    /// Signals SDL driver for new input events +    void PumpEvents() const; +  private:      struct Impl;      std::unique_ptr<Impl> impl; diff --git a/src/video_core/engines/engine_upload.cpp b/src/video_core/engines/engine_upload.cpp index 28aa85f32..e4f8331ab 100644 --- a/src/video_core/engines/engine_upload.cpp +++ b/src/video_core/engines/engine_upload.cpp @@ -49,10 +49,9 @@ void State::ProcessData(std::span<const u8> read_buffer) {          if (regs.line_count == 1) {              rasterizer->AccelerateInlineToMemory(address, copy_size, read_buffer);          } else { -            for (u32 line = 0; line < regs.line_count; ++line) { -                const GPUVAddr dest_line = address + static_cast<size_t>(line) * regs.dest.pitch; -                std::span<const u8> buffer(read_buffer.data() + -                                               static_cast<size_t>(line) * regs.line_length_in, +            for (size_t line = 0; line < regs.line_count; ++line) { +                const GPUVAddr dest_line = address + line * regs.dest.pitch; +                std::span<const u8> buffer(read_buffer.data() + line * regs.line_length_in,                                             regs.line_length_in);                  rasterizer->AccelerateInlineToMemory(dest_line, regs.line_length_in, buffer);              } diff --git a/src/video_core/engines/engine_upload.h b/src/video_core/engines/engine_upload.h index f08f6e36a..94fafd9dc 100644 --- a/src/video_core/engines/engine_upload.h +++ b/src/video_core/engines/engine_upload.h @@ -39,7 +39,7 @@ struct Registers {          u32 y;          GPUVAddr Address() const { -            return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | address_low); +            return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};          }          u32 BlockWidth() const { diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index 24b518cb5..100b21bac 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h @@ -97,7 +97,7 @@ public:          u32 addr_lower;          [[nodiscard]] constexpr GPUVAddr Address() const noexcept { -            return (static_cast<GPUVAddr>(addr_upper) << 32) | static_cast<GPUVAddr>(addr_lower); +            return (GPUVAddr{addr_upper} << 32) | GPUVAddr{addr_lower};          }      };      static_assert(sizeof(Surface) == 0x28, "Surface has incorrect size"); diff --git a/src/video_core/engines/kepler_compute.cpp b/src/video_core/engines/kepler_compute.cpp index 7c50bdbe0..e5c622155 100644 --- a/src/video_core/engines/kepler_compute.cpp +++ b/src/video_core/engines/kepler_compute.cpp @@ -50,11 +50,11 @@ void KeplerCompute::CallMultiMethod(u32 method, const u32* base_start, u32 amoun                                      u32 methods_pending) {      switch (method) {      case KEPLER_COMPUTE_REG_INDEX(data_upload): -        upload_state.ProcessData(base_start, static_cast<size_t>(amount)); +        upload_state.ProcessData(base_start, amount);          return;      default: -        for (std::size_t i = 0; i < amount; i++) { -            CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); +        for (u32 i = 0; i < amount; i++) { +            CallMethod(method, base_start[i], methods_pending - i <= 1);          }          break;      } diff --git a/src/video_core/engines/kepler_compute.h b/src/video_core/engines/kepler_compute.h index aab309ecc..e154e3f06 100644 --- a/src/video_core/engines/kepler_compute.h +++ b/src/video_core/engines/kepler_compute.h @@ -68,7 +68,7 @@ public:                  struct {                      u32 address;                      GPUVAddr Address() const { -                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address) << 8)); +                        return GPUVAddr{address} << 8;                      }                  } launch_desc_loc; @@ -83,8 +83,7 @@ public:                      u32 address_low;                      u32 limit;                      GPUVAddr Address() const { -                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                                     address_low); +                        return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};                      }                  } tsc; @@ -95,8 +94,7 @@ public:                      u32 address_low;                      u32 limit;                      GPUVAddr Address() const { -                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                                     address_low); +                        return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};                      }                  } tic; @@ -106,8 +104,7 @@ public:                      u32 address_high;                      u32 address_low;                      GPUVAddr Address() const { -                        return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                                     address_low); +                        return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};                      }                  } code_loc; @@ -162,8 +159,7 @@ public:                  BitField<15, 17, u32> size;              };              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high.Value()) << 32) | -                                             address_low); +                return (GPUVAddr{address_high.Value()} << 32) | GPUVAddr{address_low};              }          };          std::array<ConstBufferConfig, NumConstBuffers> const_buffer_config; diff --git a/src/video_core/engines/kepler_memory.cpp b/src/video_core/engines/kepler_memory.cpp index a3fbab1e5..08045d1cf 100644 --- a/src/video_core/engines/kepler_memory.cpp +++ b/src/video_core/engines/kepler_memory.cpp @@ -42,11 +42,11 @@ void KeplerMemory::CallMultiMethod(u32 method, const u32* base_start, u32 amount                                     u32 methods_pending) {      switch (method) {      case KEPLERMEMORY_REG_INDEX(data): -        upload_state.ProcessData(base_start, static_cast<size_t>(amount)); +        upload_state.ProcessData(base_start, amount);          return;      default: -        for (std::size_t i = 0; i < amount; i++) { -            CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); +        for (u32 i = 0; i < amount; i++) { +            CallMethod(method, base_start[i], methods_pending - i <= 1);          }          break;      } diff --git a/src/video_core/engines/maxwell_3d.cpp b/src/video_core/engines/maxwell_3d.cpp index 6d43e23ea..55462752c 100644 --- a/src/video_core/engines/maxwell_3d.cpp +++ b/src/video_core/engines/maxwell_3d.cpp @@ -126,6 +126,7 @@ void Maxwell3D::InitializeRegisterDefaults() {      draw_command[MAXWELL3D_REG_INDEX(draw_inline_index)] = true;      draw_command[MAXWELL3D_REG_INDEX(inline_index_2x16.even)] = true;      draw_command[MAXWELL3D_REG_INDEX(inline_index_4x8.index0)] = true; +    draw_command[MAXWELL3D_REG_INDEX(draw.instance_id)] = true;  }  void Maxwell3D::ProcessMacro(u32 method, const u32* base_start, u32 amount, bool is_last_call) { @@ -285,31 +286,58 @@ void Maxwell3D::CallMethod(u32 method, u32 method_argument, bool is_last_call) {      ASSERT_MSG(method < Regs::NUM_REGS,                 "Invalid Maxwell3D register, increase the size of the Regs structure"); +    const u32 argument = ProcessShadowRam(method, method_argument); +    ProcessDirtyRegisters(method, argument); +      if (draw_command[method]) {          regs.reg_array[method] = method_argument;          deferred_draw_method.push_back(method); -        auto u32_to_u8 = [&](const u32 argument) { -            inline_index_draw_indexes.push_back(static_cast<u8>(argument & 0x000000ff)); -            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x0000ff00) >> 8)); -            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0x00ff0000) >> 16)); -            inline_index_draw_indexes.push_back(static_cast<u8>((argument & 0xff000000) >> 24)); +        auto update_inline_index = [&](const u32 index) { +            inline_index_draw_indexes.push_back(static_cast<u8>(index & 0x000000ff)); +            inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x0000ff00) >> 8)); +            inline_index_draw_indexes.push_back(static_cast<u8>((index & 0x00ff0000) >> 16)); +            inline_index_draw_indexes.push_back(static_cast<u8>((index & 0xff000000) >> 24)); +            draw_mode = DrawMode::InlineIndex;          }; -        if (MAXWELL3D_REG_INDEX(draw_inline_index) == method) { -            u32_to_u8(method_argument); -        } else if (MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method) { -            u32_to_u8(regs.inline_index_2x16.even); -            u32_to_u8(regs.inline_index_2x16.odd); -        } else if (MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { -            u32_to_u8(regs.inline_index_4x8.index0); -            u32_to_u8(regs.inline_index_4x8.index1); -            u32_to_u8(regs.inline_index_4x8.index2); -            u32_to_u8(regs.inline_index_4x8.index3); +        switch (method) { +        case MAXWELL3D_REG_INDEX(draw.end): +            switch (draw_mode) { +            case DrawMode::General: +                ProcessDraw(1); +                break; +            case DrawMode::InlineIndex: +                regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); +                regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; +                ProcessDraw(1); +                inline_index_draw_indexes.clear(); +                break; +            case DrawMode::Instance: +                break; +            } +            break; +        case MAXWELL3D_REG_INDEX(draw_inline_index): +            update_inline_index(method_argument); +            break; +        case MAXWELL3D_REG_INDEX(inline_index_2x16.even): +            update_inline_index(regs.inline_index_2x16.even); +            update_inline_index(regs.inline_index_2x16.odd); +            break; +        case MAXWELL3D_REG_INDEX(inline_index_4x8.index0): +            update_inline_index(regs.inline_index_4x8.index0); +            update_inline_index(regs.inline_index_4x8.index1); +            update_inline_index(regs.inline_index_4x8.index2); +            update_inline_index(regs.inline_index_4x8.index3); +            break; +        case MAXWELL3D_REG_INDEX(draw.instance_id): +            draw_mode = +                (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || +                        (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) +                    ? DrawMode::Instance +                    : DrawMode::General; +            break;          }      } else {          ProcessDeferredDraw(); - -        const u32 argument = ProcessShadowRam(method, method_argument); -        ProcessDirtyRegisters(method, argument);          ProcessMethodCall(method, argument, method_argument, is_last_call);      }  } @@ -342,11 +370,11 @@ void Maxwell3D::CallMultiMethod(u32 method, const u32* base_start, u32 amount,          ProcessCBMultiData(base_start, amount);          break;      case MAXWELL3D_REG_INDEX(inline_data): -        upload_state.ProcessData(base_start, static_cast<size_t>(amount)); +        upload_state.ProcessData(base_start, amount);          return;      default: -        for (std::size_t i = 0; i < amount; i++) { -            CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); +        for (u32 i = 0; i < amount; i++) { +            CallMethod(method, base_start[i], methods_pending - i <= 1);          }          break;      } @@ -620,57 +648,27 @@ void Maxwell3D::ProcessDraw(u32 instance_count) {  }  void Maxwell3D::ProcessDeferredDraw() { -    if (deferred_draw_method.empty()) { +    if (draw_mode != DrawMode::Instance || deferred_draw_method.empty()) {          return;      } -    enum class DrawMode { -        Undefined, -        General, -        Instance, -    }; -    DrawMode draw_mode{DrawMode::Undefined}; -    u32 method_count = static_cast<u32>(deferred_draw_method.size()); -    u32 method = deferred_draw_method[method_count - 1]; -    if (MAXWELL3D_REG_INDEX(draw.end) != method) { -        return; -    } -    draw_mode = (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Subsequent) || -                        (regs.draw.instance_id == Maxwell3D::Regs::Draw::InstanceId::Unchanged) -                    ? DrawMode::Instance -                    : DrawMode::General; -    u32 instance_count = 0; -    if (draw_mode == DrawMode::Instance) { -        u32 vertex_buffer_count = 0; -        u32 index_buffer_count = 0; -        for (u32 index = 0; index < method_count; ++index) { -            method = deferred_draw_method[index]; -            if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) { -                instance_count = ++vertex_buffer_count; -            } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) { -                instance_count = ++index_buffer_count; -            } -        } -        ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), -                   "Instance both indexed and direct?"); -    } else { -        instance_count = 1; -        for (u32 index = 0; index < method_count; ++index) { -            method = deferred_draw_method[index]; -            if (MAXWELL3D_REG_INDEX(draw_inline_index) == method || -                MAXWELL3D_REG_INDEX(inline_index_2x16.even) == method || -                MAXWELL3D_REG_INDEX(inline_index_4x8.index0) == method) { -                regs.index_buffer.count = static_cast<u32>(inline_index_draw_indexes.size() / 4); -                regs.index_buffer.format = Regs::IndexFormat::UnsignedInt; -                break; -            } +    const auto method_count = deferred_draw_method.size(); +    u32 instance_count = 1; +    u32 vertex_buffer_count = 0; +    u32 index_buffer_count = 0; +    for (size_t index = 0; index < method_count; ++index) { +        const u32 method = deferred_draw_method[index]; +        if (method == MAXWELL3D_REG_INDEX(vertex_buffer.count)) { +            instance_count = ++vertex_buffer_count; +        } else if (method == MAXWELL3D_REG_INDEX(index_buffer.count)) { +            instance_count = ++index_buffer_count;          }      } +    ASSERT_MSG(!(vertex_buffer_count && index_buffer_count), "Instance both indexed and direct?");      ProcessDraw(instance_count);      deferred_draw_method.clear(); -    inline_index_draw_indexes.clear();  }  } // namespace Tegra::Engines diff --git a/src/video_core/engines/maxwell_3d.h b/src/video_core/engines/maxwell_3d.h index c3099f9a6..deba292a5 100644 --- a/src/video_core/engines/maxwell_3d.h +++ b/src/video_core/engines/maxwell_3d.h @@ -96,8 +96,7 @@ public:              u32 type;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -106,8 +105,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -124,8 +122,7 @@ public:              Mode mode;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(offset_high) << 32) | -                                             offset_low); +                return (GPUVAddr{offset_high} << 32) | GPUVAddr{offset_low};              }          }; @@ -187,7 +184,7 @@ public:                  default:                      // Thresholds begin at 0x10 (1 << 4)                      // Threshold is in the range 0x1 to 0x13 -                    return 1 << (4 + threshold.Value() - 1); +                    return 1U << (4 + threshold.Value() - 1);                  }              }          }; @@ -468,8 +465,7 @@ public:                  INSERT_PADDING_BYTES_NOINIT(0xC);                  GPUVAddr Address() const { -                    return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                                 address_low); +                    return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};                  }              };              static_assert(sizeof(Buffer) == 0x20); @@ -511,12 +507,11 @@ public:              u32 default_size_per_warp;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }              u64 Size() const { -                return (static_cast<u64>(size_high) << 32) | size_low; +                return (u64{size_high} << 32) | u64{size_low};              }          }; @@ -538,13 +533,11 @@ public:              u32 storage_limit_address_low;              GPUVAddr StorageAddress() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(storage_address_high) << 32) | -                                             storage_address_low); +                return (GPUVAddr{storage_address_high} << 32) | GPUVAddr{storage_address_low};              }              GPUVAddr StorageLimitAddress() const { -                return static_cast<GPUVAddr>( -                    (static_cast<GPUVAddr>(storage_limit_address_high) << 32) | -                    storage_limit_address_low); +                return (GPUVAddr{storage_limit_address_high} << 32) | +                       GPUVAddr{storage_limit_address_low};              }          }; @@ -829,11 +822,11 @@ public:          struct CompressionThresholdSamples {              u32 samples; -            u32 Samples() { +            u32 Samples() const {                  if (samples == 0) {                      return 0;                  } -                return 1 << (samples - 1); +                return 1U << (samples - 1);              }          }; @@ -1138,8 +1131,7 @@ public:              INSERT_PADDING_BYTES_NOINIT(0x18);              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          };          static_assert(sizeof(RenderTargetConfig) == 0x40); @@ -1482,8 +1474,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1533,8 +1524,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1561,8 +1551,7 @@ public:              u32 array_pitch;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1910,8 +1899,7 @@ public:              Mode mode;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1921,8 +1909,7 @@ public:              u32 limit;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1932,8 +1919,7 @@ public:              u32 limit;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -1981,8 +1967,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -2027,8 +2012,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -2224,19 +2208,16 @@ public:              }              GPUVAddr StartAddress() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(start_addr_high) << 32) | -                                             start_addr_low); +                return (GPUVAddr{start_addr_high} << 32) | GPUVAddr{start_addr_low};              }              GPUVAddr EndAddress() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(limit_addr_high) << 32) | -                                             limit_addr_low); +                return (GPUVAddr{limit_addr_high} << 32) | GPUVAddr{limit_addr_low};              }              /// Adjust the index buffer offset so it points to the first desired index.              GPUVAddr IndexStart() const { -                return StartAddress() + -                       static_cast<size_t>(first) * static_cast<size_t>(FormatSizeInBytes()); +                return StartAddress() + size_t{first} * size_t{FormatSizeInBytes()};              }          }; @@ -2464,8 +2445,7 @@ public:              } query;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -2479,8 +2459,7 @@ public:              u32 frequency;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }              bool IsEnabled() const { @@ -2494,8 +2473,7 @@ public:              u32 address_low;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          };          static_assert(sizeof(VertexStreamLimit) == 0x8); @@ -2543,8 +2521,7 @@ public:              std::array<u32, NumCBData> buffer;              GPUVAddr Address() const { -                return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) | -                                             address_low); +                return (GPUVAddr{address_high} << 32) | GPUVAddr{address_low};              }          }; @@ -3148,10 +3125,12 @@ private:      /// Handles use of topology overrides (e.g., to avoid using a topology assigned from a macro)      void ProcessTopologyOverride(); -    void ProcessDraw(u32 instance_count = 1); - +    /// Handles deferred draw(e.g., instance draw).      void ProcessDeferredDraw(); +    /// Handles a draw. +    void ProcessDraw(u32 instance_count = 1); +      /// Returns a query's value or an empty object if the value will be deferred through a cache.      std::optional<u64> GetQueryResult(); @@ -3178,6 +3157,8 @@ private:      std::array<bool, Regs::NUM_REGS> draw_command{};      std::vector<u32> deferred_draw_method; +    enum class DrawMode : u32 { General = 0, Instance, InlineIndex }; +    DrawMode draw_mode{DrawMode::General};  };  #define ASSERT_REG_POSITION(field_name, position)                                                  \ diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 334429514..a189e60ae 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp @@ -41,8 +41,8 @@ void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call)  void MaxwellDMA::CallMultiMethod(u32 method, const u32* base_start, u32 amount,                                   u32 methods_pending) { -    for (size_t i = 0; i < amount; ++i) { -        CallMethod(method, base_start[i], methods_pending - static_cast<u32>(i) <= 1); +    for (u32 i = 0; i < amount; ++i) { +        CallMethod(method, base_start[i], methods_pending - i <= 1);      }  } @@ -94,14 +94,14 @@ void MaxwellDMA::Launch() {                                              reinterpret_cast<u8*>(tmp_buffer.data()),                                              regs.line_length_in * sizeof(u32));          } else { -            auto convert_linear_2_blocklinear_addr = [](u64 address) { +            const auto convert_linear_2_blocklinear_addr = [](u64 address) {                  return (address & ~0x1f0ULL) | ((address & 0x40) >> 2) | ((address & 0x10) << 1) |                         ((address & 0x180) >> 1) | ((address & 0x20) << 3);              }; -            auto src_kind = memory_manager.GetPageKind(regs.offset_in); -            auto dst_kind = memory_manager.GetPageKind(regs.offset_out); -            const bool is_src_pitch = IsPitchKind(static_cast<PTEKind>(src_kind)); -            const bool is_dst_pitch = IsPitchKind(static_cast<PTEKind>(dst_kind)); +            const auto src_kind = memory_manager.GetPageKind(regs.offset_in); +            const auto dst_kind = memory_manager.GetPageKind(regs.offset_out); +            const bool is_src_pitch = IsPitchKind(src_kind); +            const bool is_dst_pitch = IsPitchKind(dst_kind);              if (!is_src_pitch && is_dst_pitch) {                  UNIMPLEMENTED_IF(regs.line_length_in % 16 != 0);                  UNIMPLEMENTED_IF(regs.offset_in % 16 != 0); diff --git a/src/video_core/engines/puller.cpp b/src/video_core/engines/puller.cpp index c308ba3fc..7718a09b3 100644 --- a/src/video_core/engines/puller.cpp +++ b/src/video_core/engines/puller.cpp @@ -31,7 +31,7 @@ void Puller::ProcessBindMethod(const MethodCall& method_call) {      LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,                method_call.argument);      const auto engine_id = static_cast<EngineID>(method_call.argument); -    bound_engines[method_call.subchannel] = static_cast<EngineID>(engine_id); +    bound_engines[method_call.subchannel] = engine_id;      switch (engine_id) {      case EngineID::FERMI_TWOD_A:          dma_pusher.BindSubchannel(channel_state.fermi_2d.get(), method_call.subchannel); @@ -285,12 +285,12 @@ void Puller::CallMultiMethod(u32 method, u32 subchannel, const u32* base_start,      if (ExecuteMethodOnEngine(method)) {          CallEngineMultiMethod(method, subchannel, base_start, amount, methods_pending);      } else { -        for (std::size_t i = 0; i < amount; i++) { +        for (u32 i = 0; i < amount; i++) {              CallPullerMethod(MethodCall{                  method,                  base_start[i],                  subchannel, -                methods_pending - static_cast<u32>(i), +                methods_pending - i,              });          }      } diff --git a/src/video_core/host1x/syncpoint_manager.cpp b/src/video_core/host1x/syncpoint_manager.cpp index a44fc83d3..8f23ce527 100644 --- a/src/video_core/host1x/syncpoint_manager.cpp +++ b/src/video_core/host1x/syncpoint_manager.cpp @@ -34,7 +34,7 @@ SyncpointManager::ActionHandle SyncpointManager::RegisterAction(  }  void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_storage, -                                        ActionHandle& handle) { +                                        const ActionHandle& handle) {      std::unique_lock lk(guard);      // We want to ensure the iterator still exists prior to erasing it @@ -49,11 +49,11 @@ void SyncpointManager::DeregisterAction(std::list<RegisteredAction>& action_stor      }  } -void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle) { +void SyncpointManager::DeregisterGuestAction(u32 syncpoint_id, const ActionHandle& handle) {      DeregisterAction(guest_action_storage[syncpoint_id], handle);  } -void SyncpointManager::DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle) { +void SyncpointManager::DeregisterHostAction(u32 syncpoint_id, const ActionHandle& handle) {      DeregisterAction(host_action_storage[syncpoint_id], handle);  } diff --git a/src/video_core/host1x/syncpoint_manager.h b/src/video_core/host1x/syncpoint_manager.h index 50a264e23..847ed20c8 100644 --- a/src/video_core/host1x/syncpoint_manager.h +++ b/src/video_core/host1x/syncpoint_manager.h @@ -36,21 +36,19 @@ public:      template <typename Func>      ActionHandle RegisterGuestAction(u32 syncpoint_id, u32 expected_value, Func&& action) { -        std::function<void()> func(action);          return RegisterAction(syncpoints_guest[syncpoint_id], guest_action_storage[syncpoint_id], -                              expected_value, std::move(func)); +                              expected_value, std::move(action));      }      template <typename Func>      ActionHandle RegisterHostAction(u32 syncpoint_id, u32 expected_value, Func&& action) { -        std::function<void()> func(action);          return RegisterAction(syncpoints_host[syncpoint_id], host_action_storage[syncpoint_id], -                              expected_value, std::move(func)); +                              expected_value, std::move(action));      } -    void DeregisterGuestAction(u32 syncpoint_id, ActionHandle& handle); +    void DeregisterGuestAction(u32 syncpoint_id, const ActionHandle& handle); -    void DeregisterHostAction(u32 syncpoint_id, ActionHandle& handle); +    void DeregisterHostAction(u32 syncpoint_id, const ActionHandle& handle);      void IncrementGuest(u32 syncpoint_id); @@ -76,7 +74,7 @@ private:                                  std::list<RegisteredAction>& action_storage, u32 expected_value,                                  std::function<void()>&& action); -    void DeregisterAction(std::list<RegisteredAction>& action_storage, ActionHandle& handle); +    void DeregisterAction(std::list<RegisteredAction>& action_storage, const ActionHandle& handle);      void Wait(std::atomic<u32>& syncpoint, std::condition_variable& wait_cv, u32 expected_value); diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 1da53f203..430a84272 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp @@ -150,7 +150,7 @@ struct FormatTuple {      {VK_FORMAT_BC6H_UFLOAT_BLOCK},                             // BC6H_UFLOAT      {VK_FORMAT_BC6H_SFLOAT_BLOCK},                             // BC6H_SFLOAT      {VK_FORMAT_ASTC_4x4_UNORM_BLOCK},                          // ASTC_2D_4X4_UNORM -    {VK_FORMAT_B8G8R8A8_UNORM, Attachable},                    // B8G8R8A8_UNORM +    {VK_FORMAT_B8G8R8A8_UNORM, Attachable | Storage},          // B8G8R8A8_UNORM      {VK_FORMAT_R32G32B32A32_SFLOAT, Attachable | Storage},     // R32G32B32A32_FLOAT      {VK_FORMAT_R32G32B32A32_SINT, Attachable | Storage},       // R32G32B32A32_SINT      {VK_FORMAT_R32G32_SFLOAT, Attachable | Storage},           // R32G32_FLOAT @@ -160,7 +160,7 @@ struct FormatTuple {      {VK_FORMAT_R16_UNORM, Attachable | Storage},               // R16_UNORM      {VK_FORMAT_R16_SNORM, Attachable | Storage},               // R16_SNORM      {VK_FORMAT_R16_UINT, Attachable | Storage},                // R16_UINT -    {VK_FORMAT_UNDEFINED},                                     // R16_SINT +    {VK_FORMAT_R16_SINT, Attachable | Storage},                // R16_SINT      {VK_FORMAT_R16G16_UNORM, Attachable | Storage},            // R16G16_UNORM      {VK_FORMAT_R16G16_SFLOAT, Attachable | Storage},           // R16G16_FLOAT      {VK_FORMAT_R16G16_UINT, Attachable | Storage},             // R16G16_UINT @@ -184,7 +184,7 @@ struct FormatTuple {      {VK_FORMAT_BC2_SRGB_BLOCK},                                // BC2_SRGB      {VK_FORMAT_BC3_SRGB_BLOCK},                                // BC3_SRGB      {VK_FORMAT_BC7_SRGB_BLOCK},                                // BC7_SRGB -    {VK_FORMAT_R4G4B4A4_UNORM_PACK16, Attachable},             // A4B4G4R4_UNORM +    {VK_FORMAT_R4G4B4A4_UNORM_PACK16},                         // A4B4G4R4_UNORM      {VK_FORMAT_R4G4_UNORM_PACK8},                              // G4R4_UNORM      {VK_FORMAT_ASTC_4x4_SRGB_BLOCK},                           // ASTC_2D_4X4_SRGB      {VK_FORMAT_ASTC_8x8_SRGB_BLOCK},                           // ASTC_2D_8X8_SRGB diff --git a/src/video_core/renderer_vulkan/vk_fsr.cpp b/src/video_core/renderer_vulkan/vk_fsr.cpp index dd450169e..33daa8c1c 100644 --- a/src/video_core/renderer_vulkan/vk_fsr.cpp +++ b/src/video_core/renderer_vulkan/vk_fsr.cpp @@ -5,6 +5,7 @@  #include "common/bit_cast.h"  #include "common/common_types.h"  #include "common/div_ceil.h" +#include "common/settings.h"  #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp16_comp_spv.h"  #include "video_core/host_shaders/vulkan_fidelityfx_fsr_easu_fp32_comp_spv.h" @@ -227,7 +228,10 @@ VkImageView FSR::Draw(Scheduler& scheduler, size_t image_index, VkImageView imag          cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *rcas_pipeline); -        FsrRcasCon(push_constants.data(), 0.25f); +        const float sharpening = +            static_cast<float>(Settings::values.fsr_sharpening_slider.GetValue()) / 100.0f; + +        FsrRcasCon(push_constants.data(), sharpening);          cmdbuf.PushConstants(*pipeline_layout, VK_SHADER_STAGE_COMPUTE_BIT, push_constants);          { diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index b618e1a25..1a76d4178 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp @@ -214,23 +214,16 @@ PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format)  }  SurfaceType GetFormatType(PixelFormat pixel_format) { -    if (static_cast<std::size_t>(pixel_format) < -        static_cast<std::size_t>(PixelFormat::MaxColorFormat)) { +    if (pixel_format < PixelFormat::MaxColorFormat) {          return SurfaceType::ColorTexture;      } - -    if (static_cast<std::size_t>(pixel_format) < -        static_cast<std::size_t>(PixelFormat::MaxDepthFormat)) { +    if (pixel_format < PixelFormat::MaxDepthFormat) {          return SurfaceType::Depth;      } - -    if (static_cast<std::size_t>(pixel_format) < -        static_cast<std::size_t>(PixelFormat::MaxStencilFormat)) { +    if (pixel_format < PixelFormat::MaxStencilFormat) {          return SurfaceType::Stencil;      } - -    if (static_cast<std::size_t>(pixel_format) < -        static_cast<std::size_t>(PixelFormat::MaxDepthStencilFormat)) { +    if (pixel_format < PixelFormat::MaxDepthStencilFormat) {          return SurfaceType::DepthStencil;      } diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index adad36221..060de0259 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt @@ -295,7 +295,7 @@ if (APPLE)      set_target_properties(yuzu PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist)  elseif(WIN32)      # compile as a win32 gui application instead of a console application -    if (QT_VERSION VERSION_GREATER 6) +    if (QT_VERSION VERSION_GREATER_EQUAL 6)          target_link_libraries(yuzu PRIVATE Qt6::EntryPointPrivate)      else()          target_link_libraries(yuzu PRIVATE Qt5::WinMain) @@ -311,15 +311,15 @@ endif()  create_target_directory_groups(yuzu)  target_link_libraries(yuzu PRIVATE common core input_common network video_core) -target_link_libraries(yuzu PRIVATE Boost::boost glad Qt::Widgets Qt::Multimedia) +target_link_libraries(yuzu PRIVATE Boost::boost glad Qt${QT_MAJOR_VERSION}::Widgets)  target_link_libraries(yuzu PRIVATE ${PLATFORM_LIBRARIES} Threads::Threads)  target_include_directories(yuzu PRIVATE ../../externals/Vulkan-Headers/include)  if (NOT WIN32) -    target_include_directories(yuzu PRIVATE ${Qt5Gui_PRIVATE_INCLUDE_DIRS}) +    target_include_directories(yuzu PRIVATE ${Qt${QT_MAJOR_VERSION}Gui_PRIVATE_INCLUDE_DIRS})  endif()  if (UNIX AND NOT APPLE) -    target_link_libraries(yuzu PRIVATE Qt::DBus) +    target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::DBus)  endif()  target_compile_definitions(yuzu PRIVATE @@ -358,8 +358,13 @@ if (ENABLE_WEB_SERVICE)      target_compile_definitions(yuzu PRIVATE -DENABLE_WEB_SERVICE)  endif() +if (YUZU_USE_QT_MULTIMEDIA) +    target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::Multimedia) +    target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_MULTIMEDIA) +endif () +  if (YUZU_USE_QT_WEB_ENGINE) -    target_link_libraries(yuzu PRIVATE Qt::WebEngineCore Qt::WebEngineWidgets) +    target_link_libraries(yuzu PRIVATE Qt${QT_MAJOR_VERSION}::WebEngineCore Qt${QT_MAJOR_VERSION}::WebEngineWidgets)      target_compile_definitions(yuzu PRIVATE -DYUZU_USE_QT_WEB_ENGINE)  endif () @@ -367,13 +372,26 @@ if(UNIX AND NOT APPLE)      install(TARGETS yuzu)  endif() -if (YUZU_USE_BUNDLED_QT) +if (WIN32 AND QT_VERSION VERSION_GREATER_EQUAL 6) +    if (MSVC AND NOT ${CMAKE_GENERATOR} STREQUAL "Ninja") +        set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin/$<CONFIG>") +    else() +        set(YUZU_EXE_DIR "${CMAKE_BINARY_DIR}/bin") +    endif() +    add_custom_command(TARGET yuzu POST_BUILD COMMAND ${WINDEPLOYQT_EXECUTABLE} "${YUZU_EXE_DIR}/yuzu.exe" --dir "${YUZU_EXE_DIR}" --libdir "${YUZU_EXE_DIR}" --plugindir "${YUZU_EXE_DIR}/plugins" --no-compiler-runtime --no-opengl-sw --no-system-d3d-compiler --no-translations --verbose 0) +endif() + +if (YUZU_USE_BUNDLED_QT AND QT_VERSION VERSION_LESS 6)      include(CopyYuzuQt5Deps)      copy_yuzu_Qt5_deps(yuzu)  endif()  if (ENABLE_SDL2) -    target_link_libraries(yuzu PRIVATE SDL2) +    if (YUZU_USE_EXTERNAL_SDL2) +        target_link_libraries(yuzu PRIVATE SDL2-static) +    else() +        target_link_libraries(yuzu PRIVATE SDL2) +    endif()      target_compile_definitions(yuzu PRIVATE HAVE_SDL2)  endif() diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp index d88efacd7..c934069dd 100644 --- a/src/yuzu/bootmanager.cpp +++ b/src/yuzu/bootmanager.cpp @@ -4,8 +4,10 @@  #include <glad/glad.h>  #include <QApplication> +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA  #include <QCameraImageCapture>  #include <QCameraInfo> +#endif  #include <QHBoxLayout>  #include <QMessageBox>  #include <QPainter> @@ -707,6 +709,7 @@ void GRenderWindow::TouchEndEvent() {  }  void GRenderWindow::InitializeCamera() { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      constexpr auto camera_update_ms = std::chrono::milliseconds{50}; // (50ms, 20Hz)      if (!Settings::values.enable_ir_sensor) {          return; @@ -760,18 +763,22 @@ void GRenderWindow::InitializeCamera() {      connect(camera_timer.get(), &QTimer::timeout, [this] { RequestCameraCapture(); });      // This timer should be dependent of camera resolution 5ms for every 100 pixels      camera_timer->start(camera_update_ms); +#endif  }  void GRenderWindow::FinalizeCamera() { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      if (camera_timer) {          camera_timer->stop();      }      if (camera) {          camera->unload();      } +#endif  }  void GRenderWindow::RequestCameraCapture() { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      if (!Settings::values.enable_ir_sensor) {          return;      } @@ -788,6 +795,7 @@ void GRenderWindow::RequestCameraCapture() {      pending_camera_snapshots++;      camera_capture->capture(); +#endif  }  void GRenderWindow::OnCameraCapture(int requestId, const QImage& img) { diff --git a/src/yuzu/bootmanager.h b/src/yuzu/bootmanager.h index c45ebf1a2..4a01481cd 100644 --- a/src/yuzu/bootmanager.h +++ b/src/yuzu/bootmanager.h @@ -241,8 +241,10 @@ private:      bool is_virtual_camera;      int pending_camera_snapshots; +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      std::unique_ptr<QCamera> camera;      std::unique_ptr<QCameraImageCapture> camera_capture; +#endif      std::unique_ptr<QTimer> camera_timer;      Core::System& system; diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 343f3b8e5..0c93df428 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp @@ -672,6 +672,7 @@ void Config::ReadRendererValues() {      ReadGlobalSetting(Settings::values.aspect_ratio);      ReadGlobalSetting(Settings::values.resolution_setup);      ReadGlobalSetting(Settings::values.scaling_filter); +    ReadGlobalSetting(Settings::values.fsr_sharpening_slider);      ReadGlobalSetting(Settings::values.anti_aliasing);      ReadGlobalSetting(Settings::values.max_anisotropy);      ReadGlobalSetting(Settings::values.use_speed_limit); @@ -1282,6 +1283,10 @@ void Config::SaveRendererValues() {                   static_cast<u32>(Settings::values.scaling_filter.GetValue(global)),                   static_cast<u32>(Settings::values.scaling_filter.GetDefault()),                   Settings::values.scaling_filter.UsingGlobal()); +    WriteSetting(QString::fromStdString(Settings::values.fsr_sharpening_slider.GetLabel()), +                 static_cast<u32>(Settings::values.fsr_sharpening_slider.GetValue(global)), +                 static_cast<u32>(Settings::values.fsr_sharpening_slider.GetDefault()), +                 Settings::values.fsr_sharpening_slider.UsingGlobal());      WriteSetting(QString::fromStdString(Settings::values.anti_aliasing.GetLabel()),                   static_cast<u32>(Settings::values.anti_aliasing.GetValue(global)),                   static_cast<u32>(Settings::values.anti_aliasing.GetDefault()), diff --git a/src/yuzu/configuration/configure_camera.cpp b/src/yuzu/configuration/configure_camera.cpp index 2a61de2a1..d95e96696 100644 --- a/src/yuzu/configuration/configure_camera.cpp +++ b/src/yuzu/configuration/configure_camera.cpp @@ -2,8 +2,11 @@  // SPDX-License-Identifier: GPL-3.0-or-later  #include <memory> +#include <QtCore> +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA  #include <QCameraImageCapture>  #include <QCameraInfo> +#endif  #include <QStandardItemModel>  #include <QTimer> @@ -33,6 +36,7 @@ ConfigureCamera::ConfigureCamera(QWidget* parent, InputCommon::InputSubsystem* i  ConfigureCamera::~ConfigureCamera() = default;  void ConfigureCamera::PreviewCamera() { +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      const auto index = ui->ir_sensor_combo_box->currentIndex();      bool camera_found = false;      const QList<QCameraInfo> cameras = QCameraInfo::availableCameras(); @@ -101,6 +105,7 @@ void ConfigureCamera::PreviewCamera() {      });      camera_timer->start(250); +#endif  }  void ConfigureCamera::DisplayCapturedFrame(int requestId, const QImage& img) { @@ -133,11 +138,13 @@ void ConfigureCamera::LoadConfiguration() {      ui->ir_sensor_combo_box->clear();      input_devices.push_back("Auto");      ui->ir_sensor_combo_box->addItem(tr("Auto")); +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      const auto cameras = QCameraInfo::availableCameras();      for (const QCameraInfo& cameraInfo : cameras) {          input_devices.push_back(cameraInfo.deviceName().toStdString());          ui->ir_sensor_combo_box->addItem(cameraInfo.description());      } +#endif      const auto current_device = Settings::values.ir_sensor_device.GetValue(); diff --git a/src/yuzu/configuration/configure_camera.h b/src/yuzu/configuration/configure_camera.h index db9833b5c..9a90512b3 100644 --- a/src/yuzu/configuration/configure_camera.h +++ b/src/yuzu/configuration/configure_camera.h @@ -46,8 +46,10 @@ private:      bool is_virtual_camera;      int pending_snapshots; +#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0)) && YUZU_USE_QT_MULTIMEDIA      std::unique_ptr<QCamera> camera;      std::unique_ptr<QCameraImageCapture> camera_capture; +#endif      std::unique_ptr<QTimer> camera_timer;      std::vector<std::string> input_devices;      std::unique_ptr<Ui::ConfigureCamera> ui; diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index bd69d04a6..f1385e972 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp @@ -63,6 +63,11 @@ ConfigureGraphics::ConfigureGraphics(const Core::System& system_, QWidget* paren          ui->api_widget->isEnabled());      ui->bg_label->setVisible(Settings::IsConfiguringGlobal());      ui->bg_combobox->setVisible(!Settings::IsConfiguringGlobal()); + +    connect(ui->fsr_sharpening_slider, &QSlider::valueChanged, this, +            &ConfigureGraphics::SetFSRIndicatorText); +    ui->fsr_sharpening_combobox->setVisible(!Settings::IsConfiguringGlobal()); +    ui->fsr_sharpening_label->setVisible(Settings::IsConfiguringGlobal());  }  void ConfigureGraphics::UpdateDeviceSelection(int device) { @@ -110,6 +115,7 @@ void ConfigureGraphics::SetConfiguration() {              static_cast<int>(Settings::values.resolution_setup.GetValue()));          ui->scaling_filter_combobox->setCurrentIndex(              static_cast<int>(Settings::values.scaling_filter.GetValue())); +        ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue());          ui->anti_aliasing_combobox->setCurrentIndex(              static_cast<int>(Settings::values.anti_aliasing.GetValue()));      } else { @@ -147,6 +153,15 @@ void ConfigureGraphics::SetConfiguration() {          ConfigurationShared::SetHighlight(ui->anti_aliasing_label,                                            !Settings::values.anti_aliasing.UsingGlobal()); +        ui->fsr_sharpening_combobox->setCurrentIndex( +            Settings::values.fsr_sharpening_slider.UsingGlobal() ? 0 : 1); +        ui->fsr_sharpening_slider->setEnabled( +            !Settings::values.fsr_sharpening_slider.UsingGlobal()); +        ui->fsr_sharpening_value->setEnabled(!Settings::values.fsr_sharpening_slider.UsingGlobal()); +        ConfigurationShared::SetHighlight(ui->fsr_sharpening_layout, +                                          !Settings::values.fsr_sharpening_slider.UsingGlobal()); +        ui->fsr_sharpening_slider->setValue(Settings::values.fsr_sharpening_slider.GetValue()); +          ui->bg_combobox->setCurrentIndex(Settings::values.bg_red.UsingGlobal() ? 0 : 1);          ui->bg_button->setEnabled(!Settings::values.bg_red.UsingGlobal());          ConfigurationShared::SetHighlight(ui->bg_layout, !Settings::values.bg_red.UsingGlobal()); @@ -155,6 +170,12 @@ void ConfigureGraphics::SetConfiguration() {                                                  Settings::values.bg_green.GetValue(),                                                  Settings::values.bg_blue.GetValue()));      UpdateAPILayout(); +    SetFSRIndicatorText(ui->fsr_sharpening_slider->sliderPosition()); +} + +void ConfigureGraphics::SetFSRIndicatorText(int percentage) { +    ui->fsr_sharpening_value->setText( +        tr("%1%", "FSR sharpening percentage (e.g. 50%)").arg(100 - (percentage / 2)));  }  void ConfigureGraphics::ApplyConfiguration() { @@ -210,6 +231,7 @@ void ConfigureGraphics::ApplyConfiguration() {          if (Settings::values.anti_aliasing.UsingGlobal()) {              Settings::values.anti_aliasing.SetValue(anti_aliasing);          } +        Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value());      } else {          if (ui->resolution_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) {              Settings::values.resolution_setup.SetGlobal(true); @@ -269,6 +291,13 @@ void ConfigureGraphics::ApplyConfiguration() {              Settings::values.bg_green.SetValue(static_cast<u8>(bg_color.green()));              Settings::values.bg_blue.SetValue(static_cast<u8>(bg_color.blue()));          } + +        if (ui->fsr_sharpening_combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { +            Settings::values.fsr_sharpening_slider.SetGlobal(true); +        } else { +            Settings::values.fsr_sharpening_slider.SetGlobal(false); +            Settings::values.fsr_sharpening_slider.SetValue(ui->fsr_sharpening_slider->value()); +        }      }  } @@ -380,6 +409,7 @@ void ConfigureGraphics::SetupPerGameUI() {          ui->aspect_ratio_combobox->setEnabled(Settings::values.aspect_ratio.UsingGlobal());          ui->resolution_combobox->setEnabled(Settings::values.resolution_setup.UsingGlobal());          ui->scaling_filter_combobox->setEnabled(Settings::values.scaling_filter.UsingGlobal()); +        ui->fsr_sharpening_slider->setEnabled(Settings::values.fsr_sharpening_slider.UsingGlobal());          ui->anti_aliasing_combobox->setEnabled(Settings::values.anti_aliasing.UsingGlobal());          ui->use_asynchronous_gpu_emulation->setEnabled(              Settings::values.use_asynchronous_gpu_emulation.UsingGlobal()); @@ -387,6 +417,7 @@ void ConfigureGraphics::SetupPerGameUI() {          ui->accelerate_astc->setEnabled(Settings::values.accelerate_astc.UsingGlobal());          ui->use_disk_shader_cache->setEnabled(Settings::values.use_disk_shader_cache.UsingGlobal());          ui->bg_button->setEnabled(Settings::values.bg_red.UsingGlobal()); +        ui->fsr_slider_layout->setEnabled(Settings::values.fsr_sharpening_slider.UsingGlobal());          return;      } @@ -396,6 +427,13 @@ void ConfigureGraphics::SetupPerGameUI() {          ConfigurationShared::SetHighlight(ui->bg_layout, index == 1);      }); +    connect(ui->fsr_sharpening_combobox, qOverload<int>(&QComboBox::activated), this, +            [this](int index) { +                ui->fsr_sharpening_slider->setEnabled(index == 1); +                ui->fsr_sharpening_value->setEnabled(index == 1); +                ConfigurationShared::SetHighlight(ui->fsr_sharpening_layout, index == 1); +            }); +      ConfigurationShared::SetColoredTristate(          ui->use_disk_shader_cache, Settings::values.use_disk_shader_cache, use_disk_shader_cache);      ConfigurationShared::SetColoredTristate(ui->accelerate_astc, Settings::values.accelerate_astc, diff --git a/src/yuzu/configuration/configure_graphics.h b/src/yuzu/configuration/configure_graphics.h index 70034eb1b..d98d6624e 100644 --- a/src/yuzu/configuration/configure_graphics.h +++ b/src/yuzu/configuration/configure_graphics.h @@ -42,6 +42,8 @@ private:      void RetrieveVulkanDevices(); +    void SetFSRIndicatorText(int percentage); +      void SetupPerGameUI();      Settings::RendererBackend GetCurrentGraphicsBackend() const; diff --git a/src/yuzu/configuration/configure_graphics.ui b/src/yuzu/configuration/configure_graphics.ui index fdbb33372..37271f956 100644 --- a/src/yuzu/configuration/configure_graphics.ui +++ b/src/yuzu/configuration/configure_graphics.ui @@ -152,6 +152,12 @@       </item>       <item>        <widget class="QGroupBox" name="groupBox"> +       <property name="maximumSize"> +        <size> +         <width>16777215</width> +         <height>16777215</height> +        </size> +       </property>         <property name="title">          <string>Graphics Settings</string>         </property> @@ -482,6 +488,146 @@           </widget>          </item>          <item> +         <widget class="QWidget" name="fsr_sharpening_layout" native="true"> +          <property name="enabled"> +           <bool>true</bool> +          </property> +          <property name="sizePolicy"> +           <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +            <horstretch>0</horstretch> +            <verstretch>0</verstretch> +           </sizepolicy> +          </property> +          <layout class="QHBoxLayout" name="horizontalLayout"> +           <property name="spacing"> +            <number>6</number> +           </property> +           <property name="sizeConstraint"> +            <enum>QLayout::SetDefaultConstraint</enum> +           </property> +           <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> +            <layout class="QHBoxLayout" name="fsr_sharpening_label_group"> +             <item> +              <widget class="QComboBox" name="fsr_sharpening_combobox"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Fixed"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <item> +                <property name="text"> +                 <string>Use global FSR Sharpness</string> +                </property> +               </item> +               <item> +                <property name="text"> +                 <string>Set FSR Sharpness</string> +                </property> +               </item> +              </widget> +             </item> +             <item> +              <widget class="QLabel" name="fsr_sharpening_label"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="text"> +                <string>FSR Sharpness:</string> +               </property> +              </widget> +             </item> +             <item> +              <spacer name="horizontalSpacer_2"> +               <property name="orientation"> +                <enum>Qt::Horizontal</enum> +               </property> +               <property name="sizeHint" stdset="0"> +                <size> +                 <width>40</width> +                 <height>20</height> +                </size> +               </property> +              </spacer> +             </item> +            </layout> +           </item> +           <item> +            <layout class="QHBoxLayout" name="fsr_slider_layout"> +             <property name="spacing"> +              <number>6</number> +             </property> +             <item> +              <widget class="QSlider" name="fsr_sharpening_slider"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="baseSize"> +                <size> +                 <width>0</width> +                 <height>0</height> +                </size> +               </property> +               <property name="maximum"> +                <number>200</number> +               </property> +               <property name="sliderPosition"> +                <number>25</number> +               </property> +               <property name="orientation"> +                <enum>Qt::Horizontal</enum> +               </property> +               <property name="invertedAppearance"> +                <bool>true</bool> +               </property> +              </widget> +             </item> +             <item> +              <widget class="QLabel" name="fsr_sharpening_value"> +               <property name="sizePolicy"> +                <sizepolicy hsizetype="Maximum" vsizetype="Preferred"> +                 <horstretch>0</horstretch> +                 <verstretch>0</verstretch> +                </sizepolicy> +               </property> +               <property name="minimumSize"> +                <size> +                 <width>32</width> +                 <height>0</height> +                </size> +               </property> +               <property name="text"> +                <string>100%</string> +               </property> +               <property name="alignment"> +                <set>Qt::AlignCenter</set> +               </property> +              </widget> +             </item> +            </layout> +           </item> +          </layout> +         </widget> +        </item> +        <item>           <widget class="QWidget" name="bg_layout" native="true">            <property name="sizePolicy">             <sizepolicy hsizetype="Preferred" vsizetype="Preferred"> diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index 10f841b98..235b813d9 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp @@ -194,4 +194,8 @@ void ConfigureInputAdvanced::UpdateUIEnabled() {      ui->mouse_panning->setEnabled(!ui->mouse_enabled->isChecked());      ui->mouse_panning_sensitivity->setEnabled(!ui->mouse_enabled->isChecked());      ui->ring_controller_configure->setEnabled(ui->enable_ring_controller->isChecked()); +#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0) || !defined(YUZU_USE_QT_MULTIMEDIA) +    ui->enable_ir_sensor->setEnabled(false); +    ui->camera_configure->setEnabled(false); +#endif  } diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 4081af391..c21153560 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -167,6 +167,7 @@ __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;  constexpr int default_mouse_hide_timeout = 2500;  constexpr int default_mouse_center_timeout = 10; +constexpr int default_input_update_timeout = 1;  /**   * "Callouts" are one-time instructional messages shown to the user. In the config settings, there @@ -237,6 +238,7 @@ static void LogRuntimes() {          LOG_INFO(Frontend, "Unable to inspect {}", runtime_dll_name);      }  #endif +    LOG_INFO(Frontend, "Qt Compile: {} Runtime: {}", QT_VERSION_STR, qVersion());  }  static QString PrettyProductName() { @@ -404,6 +406,10 @@ GMainWindow::GMainWindow(std::unique_ptr<Config> config_, bool has_broken_vulkan      mouse_center_timer.setInterval(default_mouse_center_timeout);      connect(&mouse_center_timer, &QTimer::timeout, this, &GMainWindow::CenterMouseCursor); +    update_input_timer.setInterval(default_input_update_timeout); +    connect(&update_input_timer, &QTimer::timeout, this, &GMainWindow::UpdateInputDrivers); +    update_input_timer.start(); +      MigrateConfigFiles();      if (has_broken_vulkan) { @@ -3636,6 +3642,13 @@ void GMainWindow::UpdateUISettings() {      UISettings::values.first_start = false;  } +void GMainWindow::UpdateInputDrivers() { +    if (!input_subsystem) { +        return; +    } +    input_subsystem->PumpEvents(); +} +  void GMainWindow::HideMouseCursor() {      if (emu_thread == nullptr && UISettings::values.hide_mouse) {          mouse_hide_timer.stop(); @@ -4036,7 +4049,6 @@ void GMainWindow::UpdateUITheme() {      const QString default_theme =          QString::fromUtf8(UISettings::themes[static_cast<size_t>(Config::default_theme)].second);      QString current_theme = UISettings::values.theme; -    QStringList theme_paths(default_theme_paths);      if (current_theme.isEmpty()) {          current_theme = default_theme; @@ -4049,7 +4061,7 @@ void GMainWindow::UpdateUITheme() {      if (current_theme == QStringLiteral("default") || current_theme == QStringLiteral("colorful")) {          QIcon::setThemeName(current_theme == QStringLiteral("colorful") ? current_theme                                                                          : startup_icon_theme); -        QIcon::setThemeSearchPaths(theme_paths); +        QIcon::setThemeSearchPaths(QStringList(default_theme_paths));          if (CheckDarkMode()) {              current_theme = QStringLiteral("default_dark");          } @@ -4217,10 +4229,12 @@ int main(int argc, char* argv[]) {      // so we can see if we get \u3008 instead      // TL;DR all other number formats are consecutive in unicode code points      // This bug is fixed in Qt6, specifically 6.0.0-alpha1 +#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)      const QLocale locale = QLocale::system();      if (QStringLiteral("\u3008") == locale.toString(1)) {          QLocale::setDefault(QLocale::system().name());      } +#endif      // Qt changes the locale and causes issues in float conversion using std::to_string() when      // generating shaders diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 6a9992d05..4f9c3b450 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h @@ -353,6 +353,7 @@ private:      void UpdateGPUAccuracyButton();      void UpdateStatusButtons();      void UpdateUISettings(); +    void UpdateInputDrivers();      void HideMouseCursor();      void ShowMouseCursor();      void CenterMouseCursor(); @@ -404,6 +405,7 @@ private:      bool auto_muted = false;      QTimer mouse_hide_timer;      QTimer mouse_center_timer; +    QTimer update_input_timer;      QString startup_icon_theme;      bool os_dark_mode = false; diff --git a/src/yuzu/multiplayer/direct_connect.cpp b/src/yuzu/multiplayer/direct_connect.cpp index 10bf0a4fb..cbd52da85 100644 --- a/src/yuzu/multiplayer/direct_connect.cpp +++ b/src/yuzu/multiplayer/direct_connect.cpp @@ -4,7 +4,7 @@  #include <QComboBox>  #include <QFuture>  #include <QIntValidator> -#include <QRegExpValidator> +#include <QRegularExpressionValidator>  #include <QString>  #include <QtConcurrent/QtConcurrentRun>  #include "common/settings.h" diff --git a/src/yuzu/multiplayer/validation.h b/src/yuzu/multiplayer/validation.h index dabf860be..dd25af280 100644 --- a/src/yuzu/multiplayer/validation.h +++ b/src/yuzu/multiplayer/validation.h @@ -3,7 +3,7 @@  #pragma once -#include <QRegExp> +#include <QRegularExpression>  #include <QString>  #include <QValidator> @@ -29,19 +29,21 @@ public:  private:      /// room name can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20 -    QRegExp room_name_regex = QRegExp(QStringLiteral("^[a-zA-Z0-9._- ]{4,20}$")); -    QRegExpValidator room_name; +    QRegularExpression room_name_regex = +        QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}")); +    QRegularExpressionValidator room_name;      /// nickname can be alphanumeric and " " "_" "." and "-" and must have a size of 4-20 -    QRegExp nickname_regex = QRegExp(QStringLiteral("^[a-zA-Z0-9._- ]{4,20}$")); -    QRegExpValidator nickname; +    const QRegularExpression nickname_regex = +        QRegularExpression(QStringLiteral("^[a-zA-Z0-9._ -]{4,20}")); +    QRegularExpressionValidator nickname;      /// ipv4 address only      // TODO remove this when we support hostnames in direct connect -    QRegExp ip_regex = QRegExp(QStringLiteral( +    QRegularExpression ip_regex = QRegularExpression(QStringLiteral(          "(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|"          "2[0-4][0-9]|25[0-5])")); -    QRegExpValidator ip; +    QRegularExpressionValidator ip;      /// port must be between 0 and 65535      QIntValidator port; diff --git a/src/yuzu/startup_checks.cpp b/src/yuzu/startup_checks.cpp index 6a91212e2..ccdcf10fa 100644 --- a/src/yuzu/startup_checks.cpp +++ b/src/yuzu/startup_checks.cpp @@ -4,16 +4,19 @@  #include "video_core/vulkan_common/vulkan_wrapper.h"  #ifdef _WIN32 -#include <cstring> // for memset, strncpy +#include <cstring>  #include <processthreadsapi.h>  #include <windows.h>  #elif defined(YUZU_UNIX) +#include <cstring>  #include <errno.h> +#include <spawn.h> +#include <sys/types.h>  #include <sys/wait.h>  #include <unistd.h>  #endif -#include <cstdio> +#include <fmt/core.h>  #include "video_core/vulkan_common/vulkan_instance.h"  #include "video_core/vulkan_common/vulkan_library.h"  #include "yuzu/startup_checks.h" @@ -27,7 +30,7 @@ void CheckVulkan() {              Vulkan::CreateInstance(library, dld, VK_API_VERSION_1_0);      } catch (const Vulkan::vk::Exception& exception) { -        std::fprintf(stderr, "Failed to initialize Vulkan: %s\n", exception.what()); +        fmt::print(stderr, "Failed to initialize Vulkan: {}\n", exception.what());      }  } @@ -49,8 +52,15 @@ bool CheckEnvVars(bool* is_child) {          *is_child = true;          return false;      } else if (!SetEnvironmentVariableA(IS_CHILD_ENV_VAR, ENV_VAR_ENABLED_TEXT)) { -        std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n", -                     IS_CHILD_ENV_VAR, GetLastError()); +        fmt::print(stderr, "SetEnvironmentVariableA failed to set {} with error {}\n", +                   IS_CHILD_ENV_VAR, GetLastError()); +        return true; +    } +#elif defined(YUZU_UNIX) +    const char* startup_check_var = getenv(STARTUP_CHECK_ENV_VAR); +    if (startup_check_var != nullptr && +        std::strncmp(startup_check_var, ENV_VAR_ENABLED_TEXT, 8) == 0) { +        CheckVulkan();          return true;      }  #endif @@ -62,8 +72,8 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka      // Set the startup variable for child processes      const bool env_var_set = SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT);      if (!env_var_set) { -        std::fprintf(stderr, "SetEnvironmentVariableA failed to set %s with error %lu\n", -                     STARTUP_CHECK_ENV_VAR, GetLastError()); +        fmt::print(stderr, "SetEnvironmentVariableA failed to set {} with error {}\n", +                   STARTUP_CHECK_ENV_VAR, GetLastError());          return false;      } @@ -81,48 +91,57 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka          DWORD exit_code = STILL_ACTIVE;          const int err = GetExitCodeProcess(process_info.hProcess, &exit_code);          if (err == 0) { -            std::fprintf(stderr, "GetExitCodeProcess failed with error %lu\n", GetLastError()); +            fmt::print(stderr, "GetExitCodeProcess failed with error {}\n", GetLastError());          }          // Vulkan is broken if the child crashed (return value is not zero)          *has_broken_vulkan = (exit_code != 0);          if (CloseHandle(process_info.hProcess) == 0) { -            std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError()); +            fmt::print(stderr, "CloseHandle failed with error {}\n", GetLastError());          }          if (CloseHandle(process_info.hThread) == 0) { -            std::fprintf(stderr, "CloseHandle failed with error %lu\n", GetLastError()); +            fmt::print(stderr, "CloseHandle failed with error {}\n", GetLastError());          }      }      if (!SetEnvironmentVariableA(STARTUP_CHECK_ENV_VAR, nullptr)) { -        std::fprintf(stderr, "SetEnvironmentVariableA failed to clear %s with error %lu\n", -                     STARTUP_CHECK_ENV_VAR, GetLastError()); +        fmt::print(stderr, "SetEnvironmentVariableA failed to clear {} with error {}\n", +                   STARTUP_CHECK_ENV_VAR, GetLastError());      }  #elif defined(YUZU_UNIX) +    const int env_var_set = setenv(STARTUP_CHECK_ENV_VAR, ENV_VAR_ENABLED_TEXT, 1); +    if (env_var_set == -1) { +        const int err = errno; +        fmt::print(stderr, "setenv failed to set {} with error {}\n", STARTUP_CHECK_ENV_VAR, err); +        return false; +    } +      if (perform_vulkan_check) { -        const pid_t pid = fork(); -        if (pid == 0) { -            CheckVulkan(); -            return true; -        } else if (pid == -1) { -            const int err = errno; -            std::fprintf(stderr, "fork failed with error %d\n", err); +        const pid_t pid = SpawnChild(arg0); +        if (pid == -1) {              return false;          }          // Get exit code from child process          int status; -        const int r_val = wait(&status); +        const int r_val = waitpid(pid, &status, 0);          if (r_val == -1) {              const int err = errno; -            std::fprintf(stderr, "wait failed with error %d\n", err); +            fmt::print(stderr, "wait failed with error {}\n", err);              return false;          }          // Vulkan is broken if the child crashed (return value is not zero)          *has_broken_vulkan = (status != 0);      } + +    const int env_var_cleared = unsetenv(STARTUP_CHECK_ENV_VAR); +    if (env_var_cleared == -1) { +        const int err = errno; +        fmt::print(stderr, "unsetenv failed to clear {} with error {}\n", STARTUP_CHECK_ENV_VAR, +                   err); +    }  #endif      return false;  } @@ -150,10 +169,29 @@ bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags) {                                                  pi             // lpProcessInformation      );      if (!process_created) { -        std::fprintf(stderr, "CreateProcessA failed with error %lu\n", GetLastError()); +        fmt::print(stderr, "CreateProcessA failed with error {}\n", GetLastError());          return false;      }      return true;  } +#elif defined(YUZU_UNIX) +pid_t SpawnChild(const char* arg0) { +    const pid_t pid = fork(); + +    if (pid == -1) { +        // error +        const int err = errno; +        fmt::print(stderr, "fork failed with error {}\n", err); +        return pid; +    } else if (pid == 0) { +        // child +        execl(arg0, arg0, nullptr); +        const int err = errno; +        fmt::print(stderr, "execl failed with error {}\n", err); +        _exit(0); +    } + +    return pid; +}  #endif diff --git a/src/yuzu/startup_checks.h b/src/yuzu/startup_checks.h index d8e563be6..2f86fb843 100644 --- a/src/yuzu/startup_checks.h +++ b/src/yuzu/startup_checks.h @@ -5,6 +5,8 @@  #ifdef _WIN32  #include <windows.h> +#elif defined(YUZU_UNIX) +#include <sys/types.h>  #endif  constexpr char IS_CHILD_ENV_VAR[] = "YUZU_IS_CHILD"; @@ -17,4 +19,6 @@ bool StartupChecks(const char* arg0, bool* has_broken_vulkan, bool perform_vulka  #ifdef _WIN32  bool SpawnChild(const char* arg0, PROCESS_INFORMATION* pi, int flags); +#elif defined(YUZU_UNIX) +pid_t SpawnChild(const char* arg0);  #endif diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 66dd0dc15..59f9c8e09 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp @@ -90,7 +90,11 @@ static const std::array<std::array<int, 5>, Settings::NativeAnalog::NumAnalogs>  template <>  void Config::ReadSetting(const std::string& group, Settings::Setting<std::string>& setting) { -    setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); +    std::string setting_value = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); +    if (setting_value.empty()) { +        setting_value = setting.GetDefault(); +    } +    setting = std::move(setting_value);  }  template <> @@ -299,6 +303,7 @@ void Config::ReadValues() {      ReadSetting("Renderer", Settings::values.resolution_setup);      ReadSetting("Renderer", Settings::values.scaling_filter); +    ReadSetting("Renderer", Settings::values.fsr_sharpening_slider);      ReadSetting("Renderer", Settings::values.anti_aliasing);      ReadSetting("Renderer", Settings::values.fullscreen_mode);      ReadSetting("Renderer", Settings::values.aspect_ratio); diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index d214771b0..5bbc3f532 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h @@ -6,16 +6,22 @@  namespace DefaultINI {  const char* sdl2_config_file = R"( -[ControlsGeneral] + +[ControlsP0]  # The input devices and parameters for each Switch native input +# The config section determines the player number where the config will be applied on. For example "ControlsP0", "ControlsP1", ...  # It should be in the format of "engine:[engine_name],[param1]:[value1],[param2]:[value2]..."  # Escape characters $0 (for ':'), $1 (for ',') and $2 (for '$') can be used in values +# Indicates if this player should be connected at boot +connected= +  # for button input, the following devices are available:  #  - "keyboard" (default) for keyboard input. Required parameters:  #      - "code": the code of the key to bind  #  - "sdl" for joystick input using SDL. Required parameters: -#      - "joystick": the index of the joystick to bind +#      - "guid": SDL identification GUID of the joystick +#      - "port": the index of the joystick to bind  #      - "button"(optional): the index of the button to bind  #      - "hat"(optional): the index of the hat to bind as direction buttons  #      - "axis"(optional): the index of the axis to bind @@ -58,12 +64,29 @@ button_screenshot=  #      - "modifier_scale": a float number representing the applied modifier scale to the analog input.  #          Must be in range of 0.0-1.0. Defaults to 0.5  #  - "sdl" for joystick input using SDL. Required parameters: -#      - "joystick": the index of the joystick to bind +#      - "guid": SDL identification GUID of the joystick +#      - "port": the index of the joystick to bind  #      - "axis_x": the index of the axis to bind as x-axis (default to 0)  #      - "axis_y": the index of the axis to bind as y-axis (default to 1)  lstick=  rstick= +# for motion input, the following devices are available: +#  - "keyboard" (default) for emulating random motion input from buttons. Required parameters: +#      - "code": the code of the key to bind +#  - "sdl" for motion input using SDL. Required parameters: +#      - "guid": SDL identification GUID of the joystick +#      - "port": the index of the joystick to bind +#      - "motion": the index of the motion sensor to bind +#  - "cemuhookudp" for motion input using Cemu Hook protocol. Required parameters: +#      - "guid": the IP address of the cemu hook server encoded to a hex string. for example 192.168.0.1 = "c0a80001" +#      - "port": the port of the cemu hook server +#      - "pad": the index of the joystick +#      - "motion": the index of the motion sensor of the joystick to bind +motionleft= +motionright= + +[ControlsGeneral]  # To use the debug_pad, prepend `debug_pad_` before each button setting above.  # i.e. debug_pad_button_a= diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 4ac72c2f6..37dd1747c 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp @@ -7,6 +7,7 @@  #include "common/scm_rev.h"  #include "common/settings.h"  #include "core/core.h" +#include "core/hid/hid_core.h"  #include "core/perf_stats.h"  #include "input_common/drivers/keyboard.h"  #include "input_common/drivers/mouse.h" @@ -26,6 +27,7 @@ EmuWindow_SDL2::EmuWindow_SDL2(InputCommon::InputSubsystem* input_subsystem_, Co  }  EmuWindow_SDL2::~EmuWindow_SDL2() { +    system.HIDCore().UnloadInputDevices();      input_subsystem->Shutdown();      SDL_Quit();  } | 
