Compare commits
266 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 56b0f979eb | |||
| fd1ea0fd84 | |||
| 48108a8c9b | |||
| 5da72a891f | |||
| f8a7d6a0ae | |||
| da31326c17 | |||
| 45672d43e3 | |||
| a3bac5550d | |||
| 4faea2bbf4 | |||
| fa10374d39 | |||
| 98135dee16 | |||
| 243404bf34 | |||
| 7bf4bec257 | |||
| f7d95d0a3a | |||
| bbb202ceed | |||
| 789da737af | |||
| b541a35e27 | |||
| 6bc1a477bf | |||
| 9bfd4d880e | |||
| 6a56f42f5d | |||
| b81caf1879 | |||
| b1d633532f | |||
| 12c0f682e6 | |||
| 9ff891ce71 | |||
| 82d80869fc | |||
| 20cbf6f3db | |||
| dca4f0687a | |||
| b8c03411e7 | |||
| 3ff7a5de1a | |||
| 4447c9a46e | |||
| e2f32e8c88 | |||
| beba9c9b61 | |||
| a222f02c7a | |||
| 0104e28fe4 | |||
| c5f519e1e4 | |||
| 5a5bb91f40 | |||
| 4fce72c902 | |||
| 77b0d01639 | |||
| 18bdf45868 | |||
| 09e3029c11 | |||
| 2221afaf26 | |||
| 45fcde817e | |||
| 29fbce9fe6 | |||
| 5754456292 | |||
| 3cc3176ad6 | |||
| d5f53da79d | |||
| a4696285af | |||
| 179adee396 | |||
| f44c60321e | |||
| f6868ae4dd | |||
| 0ed80c9818 | |||
| 339a37f8cb | |||
| da58eb6208 | |||
| b32b9524ad | |||
| 3e1e6c66c0 | |||
| 8ef9075b1b | |||
| 0c531ff911 | |||
| d5684dbe7d | |||
| ed37192441 | |||
| 623429a27e | |||
| 456322dde6 | |||
| 821da3ed54 | |||
| 8d1d6e149f | |||
| 1085bbb0a3 | |||
| a5bc86a9ac | |||
| 6982423931 | |||
| e532b74e11 | |||
| 985ed1e160 | |||
| f6e705737a | |||
| 66c4331de5 | |||
| c586ac9be2 | |||
| 0e265db873 | |||
| 5b837157bd | |||
| 37014e9127 | |||
| 1e64b5e2ec | |||
| 15d63c3d3d | |||
| 41461514d6 | |||
| bf0b957c05 | |||
| bfdd512787 | |||
| 9704acb982 | |||
| e1f5f4bdea | |||
| 08d4e7c7af | |||
| 4b7e73e0a6 | |||
| d8534ea140 | |||
| bbdb6d391e | |||
| a86af1b776 | |||
| 131ed37803 | |||
| a225ba4cda | |||
| e86e144a7c | |||
| 99494e77c3 | |||
| dba84458be | |||
| bb3440f7c4 | |||
| f385175aa2 | |||
| 7c68f93bdf | |||
| 04779b3d2a | |||
| 90145c424d | |||
| 7e7a23363a | |||
| eadc1ae1e7 | |||
| e7f9f58fa4 | |||
| e6ae720c33 | |||
| fedd857054 | |||
| d8da9a2afd | |||
| 2b40cdf04f | |||
| a84676c2aa | |||
| e26c86a6e7 | |||
| 9bbb77637e | |||
| bcf59ff3a7 | |||
| e4a16f50ef | |||
| 87543b9dea | |||
| 7bf4b45349 | |||
| 4255e30722 | |||
| 78eeefb030 | |||
| efa8711bf3 | |||
| c3fd211b43 | |||
| dcca650599 | |||
| dddc9bb8f1 | |||
| 4769d798f9 | |||
| 7381f873e9 | |||
| 3b19f741bd | |||
| c7f32300b2 | |||
| 6352c5dc31 | |||
| 752236caad | |||
| a52d0b82a6 | |||
| cec3a3cd5a | |||
| 3b9db85646 | |||
| 522e7c5663 | |||
| ec547824f1 | |||
| 919b4acfea | |||
| 8e17b5469f | |||
| 0cbfdf7ecb | |||
| 157981cac5 | |||
| 18831e0933 | |||
| ea56d8f388 | |||
| f23f875dd8 | |||
| 06a67d2bbd | |||
| bbc1809951 | |||
| a9633ba8b2 | |||
| 7fc6514be1 | |||
| e44a804ec7 | |||
| a948ab3e48 | |||
| f4b5570e7c | |||
| 02b10a6e4d | |||
| 6d2c597371 | |||
| 14440b195c | |||
| f77cc6c412 | |||
| 75e16547f8 | |||
| 22aff09b33 | |||
| ac0721a4bc | |||
| c043ba8467 | |||
| 9a5d8b356a | |||
| 6072b22a0b | |||
| d8bd52c6f1 | |||
| a4725bcb73 | |||
| dcc663e1bf | |||
| 3ef006b5ab | |||
| cb5400b34d | |||
| e67b829cc7 | |||
| 5ff19890e9 | |||
| 2d2be2facf | |||
| 5e647fe69a | |||
| be05cb640c | |||
| 5b5612c1cc | |||
| 3c39c0ac3e | |||
| 4e89979c87 | |||
| 8fd4e44014 | |||
| 51358d2b5e | |||
| a78372110c | |||
| 49219b8a86 | |||
| 37bc5118ea | |||
| 5695ae6bdd | |||
| cae6c13ffb | |||
| d6b63239ae | |||
| cafca891ea | |||
| c845d8a9e8 | |||
| 1a6785d296 | |||
| b6d93b2c77 | |||
| c4af7b3f5c | |||
| 96ffc174aa | |||
| d7ec031419 | |||
| 55a3cbfa0d | |||
| 55b546a110 | |||
| 6b8ab9ed8f | |||
| a7f1fa7bfc | |||
| b6373c5ea5 | |||
| 0941ae0b61 | |||
| 00fdffec58 | |||
| 47b133c0b8 | |||
| a9efea8ae9 | |||
| 89dd7dc180 | |||
| 25dda06f49 | |||
| 4cbbf590e3 | |||
| 3de05726eb | |||
| b1b20ad84a | |||
| ae74f46e78 | |||
| 3020f72b0c | |||
| c0c4f6dfa6 | |||
| 260a495a23 | |||
| 7a329ae56c | |||
| d0883027d6 | |||
| bbb963a31a | |||
| 51abe35e05 | |||
| 64ff79f919 | |||
| e507c01a22 | |||
| ad787b20ca | |||
| c2c9b44749 | |||
| 8265c167d3 | |||
| 780ae92265 | |||
| 2ec7d0b5fd | |||
| 7f42432f42 | |||
| e96f55b6e2 | |||
| 6291eec700 | |||
| aaada241dc | |||
| 6b64557ad6 | |||
| a2fde04da9 | |||
| 2956a33463 | |||
| 71f2b4ba8f | |||
| 7d8095d944 | |||
| a67e776af9 | |||
| 3ab8d9ac7c | |||
| ef6144bf48 | |||
| 278c0e6e8d | |||
| 4a46da6fb5 | |||
| eabe45346f | |||
| 8f6245be9a | |||
| 701ca96827 | |||
| 26211ac339 | |||
| 3e53d8138c | |||
| ddca512f3f | |||
| 972bd6cb54 | |||
| c8d84cb6cb | |||
| 19a640286c | |||
| b670c350e4 | |||
| e16d1b85f1 | |||
| 2572b0a5ea | |||
| e8cbc3b4c5 | |||
| 64965cc658 | |||
| 20b62dbd30 | |||
| 9d081a8729 | |||
| 826e0785bf | |||
| 3b582d5fb2 | |||
| 7356ab1de6 | |||
| daf2ef8f1c | |||
| 5fbd6954ef | |||
| 957840be91 | |||
| a75542ad2d | |||
| f209e976f4 | |||
| 35319ca3a5 | |||
| 3e6c835a64 | |||
| 852de7a771 | |||
| ca154d466a | |||
| 97f273e94e | |||
| 59335f6796 | |||
| c31f19b6d1 | |||
| 9abceaed61 | |||
| cdb2e4eaff | |||
| 9737615948 | |||
| 168c9ee341 | |||
| 8d99aae45b | |||
| f047f376d4 | |||
| 1d57851fc7 | |||
| 9efdad6a27 | |||
| db7bcd51ae | |||
| 327d225c3e | |||
| d23a35dfbd | |||
| ad3ee5c52b | |||
| 0d6a8824d0 |
@@ -11,6 +11,7 @@ ccache -s
|
||||
mkdir build || true && cd build
|
||||
cmake .. \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/clang++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/clang \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
@@ -19,6 +20,7 @@ cmake .. \
|
||||
-DENABLE_QT_TRANSLATION=ON \
|
||||
-DUSE_DISCORD_PRESENCE=ON \
|
||||
-DYUZU_ENABLE_COMPATIBILITY_REPORTING=${ENABLE_COMPATIBILITY_REPORTING:-"OFF"} \
|
||||
-DYUZU_USE_BUNDLED_FFMPEG=ON \
|
||||
-GNinja
|
||||
|
||||
ninja
|
||||
|
||||
@@ -12,6 +12,7 @@ mkdir build || true && cd build
|
||||
cmake .. \
|
||||
-DBoost_USE_STATIC_LIBS=ON \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_CXX_FLAGS="-march=x86-64-v2" \
|
||||
-DCMAKE_CXX_COMPILER=/usr/lib/ccache/g++ \
|
||||
-DCMAKE_C_COMPILER=/usr/lib/ccache/gcc \
|
||||
-DCMAKE_INSTALL_PREFIX="/usr" \
|
||||
|
||||
@@ -9,7 +9,7 @@ parameters:
|
||||
steps:
|
||||
- script: choco install vulkan-sdk
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -G "Visual Studio 17 2022" -A x64 -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
- script: refreshenv && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_INTERPROCEDURAL_OPTIMIZATION=ON -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_USE_BUNDLED_QT=1 -DYUZU_USE_BUNDLED_SDL2=1 -DYUZU_USE_QT_WEB_ENGINE=ON -DENABLE_COMPATIBILITY_LIST_DOWNLOAD=ON -DYUZU_ENABLE_COMPATIBILITY_REPORTING=${COMPAT} -DYUZU_TESTS=OFF -DUSE_DISCORD_PRESENCE=ON -DENABLE_QT_TRANSLATION=ON -DDISPLAY_VERSION=${{ parameters['version'] }} -DCMAKE_BUILD_TYPE=Release -DYUZU_CRASH_DUMPS=ON .. && cd ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
url = https://github.com/KhronosGroup/Vulkan-Headers.git
|
||||
[submodule "sirit"]
|
||||
path = externals/sirit
|
||||
url = https://github.com/ReinUsesLisp/sirit
|
||||
url = https://github.com/yuzu-emu/sirit
|
||||
[submodule "mbedtls"]
|
||||
path = externals/mbedtls
|
||||
url = https://github.com/yuzu-emu/mbedtls
|
||||
|
||||
+229
-178
@@ -1,7 +1,11 @@
|
||||
# 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)
|
||||
|
||||
# Dynarmic has cmake_minimum_required(3.12) and we may want to override
|
||||
# some of its variables, which is only possible in 3.13+
|
||||
set(CMAKE_POLICY_DEFAULT_CMP0077 NEW)
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/CMakeModules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modules")
|
||||
@@ -18,32 +22,39 @@ CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON
|
||||
# On Linux system SDL2 is likely to be lacking HIDAPI support which have drawbacks but is needed for SDL motion
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
|
||||
|
||||
option(ENABLE_OPENGL "Enable OpenGL" ON)
|
||||
mark_as_advanced(FORCE ENABLE_OPENGL)
|
||||
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)
|
||||
|
||||
option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||
|
||||
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)
|
||||
|
||||
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
|
||||
|
||||
option(YUZU_USE_BUNDLED_OPUS "Compile bundled opus" ON)
|
||||
|
||||
option(YUZU_TESTS "Compile tests" ON)
|
||||
|
||||
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile Windows crash dump (Minidump) support" OFF "WIN32" OFF)
|
||||
|
||||
option(YUZU_USE_BUNDLED_VCPKG "Use vcpkg for yuzu dependencies" "${MSVC}")
|
||||
|
||||
option(YUZU_CHECK_SUBMODULES "Check if submodules are present" ON)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
||||
|
||||
if (YUZU_USE_BUNDLED_VCPKG)
|
||||
if (YUZU_TESTS)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "yuzu-tests")
|
||||
@@ -59,6 +70,21 @@ elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
|
||||
include("$ENV{VCPKG_TOOLCHAIN_FILE}")
|
||||
endif()
|
||||
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
if (MSVC AND CCACHE)
|
||||
# buildcache does not properly cache PCH files, leading to compilation errors.
|
||||
# See https://github.com/mbitsnbites/buildcache/discussions/230
|
||||
message(WARNING "buildcache does not properly support Precompiled Headers. Disabling PCH")
|
||||
set(DYNARMIC_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
|
||||
set(YUZU_USE_PRECOMPILED_HEADERS OFF CACHE BOOL "" FORCE)
|
||||
endif()
|
||||
endif()
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
message(STATUS "Using Precompiled Headers.")
|
||||
set(CMAKE_PCH_INSTANTIATE_TEMPLATES ON)
|
||||
endif()
|
||||
|
||||
|
||||
# Default to a Release build
|
||||
get_property(IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
|
||||
if (NOT IS_MULTI_CONFIG AND NOT CMAKE_BUILD_TYPE)
|
||||
@@ -175,24 +201,40 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
# System imported libraries
|
||||
# =======================================================================
|
||||
|
||||
find_package(fmt 8.0.1 REQUIRED CONFIG)
|
||||
find_package(nlohmann_json 3.8 REQUIRED CONFIG)
|
||||
find_package(enet 1.3)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(inih)
|
||||
find_package(libusb 1.0.24)
|
||||
find_package(lz4 REQUIRED)
|
||||
find_package(nlohmann_json 3.8 REQUIRED)
|
||||
find_package(Opus 1.3)
|
||||
find_package(Vulkan 1.3.213)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
|
||||
# Search for config-only package first (for vcpkg), then try non-config
|
||||
find_package(zstd 1.5 CONFIG)
|
||||
if (NOT zstd_FOUND)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak 6)
|
||||
endif()
|
||||
|
||||
# lz4 1.8 is required, but vcpkg's lz4-config.cmake does not have version info
|
||||
find_package(lz4 CONFIG)
|
||||
if (NOT lz4_FOUND)
|
||||
find_package(lz4 1.8 REQUIRED)
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
find_package(dynarmic 6.4.0)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CUBEB)
|
||||
find_package(cubeb)
|
||||
endif()
|
||||
|
||||
if (USE_DISCORD_PRESENCE)
|
||||
find_package(DiscordRPC)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(cpp-jwt 1.4)
|
||||
find_package(httplib 0.11)
|
||||
endif()
|
||||
|
||||
if (YUZU_TESTS)
|
||||
find_package(Catch2 2.13.7 REQUIRED CONFIG)
|
||||
find_package(Catch2 2.13.7 REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Boost 1.73.0 COMPONENTS context)
|
||||
@@ -213,128 +255,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.")
|
||||
endif()
|
||||
|
||||
# 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 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})
|
||||
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)
|
||||
endif()
|
||||
set_yuzu_qt_components()
|
||||
if (ENABLE_QT6)
|
||||
find_package(Qt6 ${QT6_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS})
|
||||
endif()
|
||||
|
||||
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 (DEFINED QT_BUILD)
|
||||
download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX)
|
||||
endif()
|
||||
|
||||
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})
|
||||
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()
|
||||
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)
|
||||
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 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 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 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)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
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 (DEFINED QT_BUILD)
|
||||
download_bundled_external("qt/" ${QT_BUILD} QT_PREFIX)
|
||||
endif()
|
||||
|
||||
set(QT_PREFIX_HINT HINTS "${QT_PREFIX}")
|
||||
|
||||
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()
|
||||
|
||||
set_yuzu_qt_components()
|
||||
find_package(Qt5 ${QT5_VERSION} COMPONENTS ${YUZU_QT_COMPONENTS} ${QT_PREFIX_HINT} ${YUZU_QT_NO_CMAKE_SYSTEM_PATH})
|
||||
endif()
|
||||
|
||||
if (ENABLE_QT_TRANSLATION)
|
||||
find_package(Qt5 REQUIRED COMPONENTS LinguistTools ${QT_PREFIX_HINT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the yuzu_find_package
|
||||
@@ -356,23 +436,13 @@ if (ENABLE_SDL2)
|
||||
set(SDL2_LIBRARY "${SDL2_PREFIX}/lib/x64/SDL2.lib" CACHE PATH "Path to SDL2 library")
|
||||
set(SDL2_DLL_DIR "${SDL2_PREFIX}/lib/x64/" CACHE PATH "Path to SDL2.dll")
|
||||
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARY}")
|
||||
target_include_directories(SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
|
||||
add_library(SDL2::SDL2 INTERFACE IMPORTED)
|
||||
target_link_libraries(SDL2::SDL2 INTERFACE "${SDL2_LIBRARY}")
|
||||
target_include_directories(SDL2::SDL2 INTERFACE "${SDL2_INCLUDE_DIR}")
|
||||
elseif (YUZU_USE_EXTERNAL_SDL2)
|
||||
message(STATUS "Using SDL2 from externals.")
|
||||
else()
|
||||
find_package(SDL2 2.0.18 REQUIRED)
|
||||
|
||||
# Some installations don't set SDL2_LIBRARIES
|
||||
if("${SDL2_LIBRARIES}" STREQUAL "")
|
||||
message(WARNING "SDL2_LIBRARIES wasn't set, manually setting to SDL2::SDL2")
|
||||
set(SDL2_LIBRARIES "SDL2::SDL2")
|
||||
endif()
|
||||
|
||||
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
|
||||
add_library(SDL2 INTERFACE)
|
||||
target_link_libraries(SDL2 INTERFACE "${SDL2_LIBRARIES}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -384,25 +454,6 @@ if (TARGET Boost::boost)
|
||||
add_library(boost ALIAS Boost::boost)
|
||||
endif()
|
||||
|
||||
# Ensure libusb is properly configured (based on dolphin libusb include)
|
||||
if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB)
|
||||
find_package(PkgConfig)
|
||||
if (PKG_CONFIG_FOUND AND NOT CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD")
|
||||
pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24)
|
||||
else()
|
||||
find_package(LibUSB)
|
||||
endif()
|
||||
|
||||
if (LIBUSB_FOUND)
|
||||
add_library(usb INTERFACE)
|
||||
target_include_directories(usb INTERFACE "${LIBUSB_INCLUDE_DIRS}")
|
||||
target_link_libraries(usb INTERFACE "${LIBUSB_LIBRARIES}")
|
||||
else()
|
||||
message(WARNING "libusb not found, falling back to externals")
|
||||
set(YUZU_USE_BUNDLED_LIBUSB ON)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# List of all FFmpeg components required
|
||||
set(FFmpeg_COMPONENTS
|
||||
avcodec
|
||||
@@ -415,22 +466,7 @@ if (UNIX AND NOT APPLE)
|
||||
endif()
|
||||
if (NOT YUZU_USE_BUNDLED_FFMPEG)
|
||||
# Use system installed FFmpeg
|
||||
find_package(FFmpeg 4.3 QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
|
||||
if (FFmpeg_FOUND)
|
||||
# Overwrite aggregate defines from FFmpeg module to avoid over-linking libraries.
|
||||
# Prevents shipping too many libraries with the AppImage.
|
||||
set(FFmpeg_LIBRARIES "")
|
||||
set(FFmpeg_INCLUDE_DIR "")
|
||||
|
||||
foreach(COMPONENT ${FFmpeg_COMPONENTS})
|
||||
set(FFmpeg_LIBRARIES ${FFmpeg_LIBRARIES} ${FFmpeg_LIBRARY_${COMPONENT}} CACHE PATH "Paths to FFmpeg libraries" FORCE)
|
||||
set(FFmpeg_INCLUDE_DIR ${FFmpeg_INCLUDE_DIR} ${FFmpeg_INCLUDE_${COMPONENT}} CACHE PATH "Path to FFmpeg headers" FORCE)
|
||||
endforeach()
|
||||
else()
|
||||
message(WARNING "FFmpeg not found or too old, falling back to externals")
|
||||
set(YUZU_USE_BUNDLED_FFMPEG ON)
|
||||
endif()
|
||||
find_package(FFmpeg 4.3 REQUIRED QUIET COMPONENTS ${FFmpeg_COMPONENTS})
|
||||
endif()
|
||||
|
||||
# Prefer the -pthread flag on Linux.
|
||||
@@ -547,6 +583,21 @@ if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
)
|
||||
endif()
|
||||
|
||||
if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
# We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default.
|
||||
# Try to pick a faster linker.
|
||||
find_program(LLD lld)
|
||||
find_program(MOLD mold)
|
||||
|
||||
if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1")
|
||||
message(NOTICE "Selecting mold as linker")
|
||||
add_link_options("-fuse-ld=mold")
|
||||
elseif (LLD)
|
||||
message(NOTICE "Selecting lld as linker")
|
||||
add_link_options("-fuse-ld=lld")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
||||
|
||||
@@ -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>.*
|
||||
|
||||
Vendored
+778
-572
File diff suppressed because it is too large
Load Diff
Vendored
+778
-568
File diff suppressed because it is too large
Load Diff
Vendored
+892
-664
File diff suppressed because it is too large
Load Diff
Vendored
+803
-593
File diff suppressed because it is too large
Load Diff
Vendored
+824
-611
File diff suppressed because it is too large
Load Diff
Vendored
+823
-614
File diff suppressed because it is too large
Load Diff
Vendored
+807
-597
File diff suppressed because it is too large
Load Diff
Vendored
+778
-567
File diff suppressed because it is too large
Load Diff
Vendored
+897
-682
File diff suppressed because it is too large
Load Diff
Vendored
+783
-573
File diff suppressed because it is too large
Load Diff
Vendored
+808
-597
File diff suppressed because it is too large
Load Diff
Vendored
+781
-570
File diff suppressed because it is too large
Load Diff
Vendored
+807
-596
File diff suppressed because it is too large
Load Diff
Vendored
+782
-576
File diff suppressed because it is too large
Load Diff
Vendored
+782
-576
File diff suppressed because it is too large
Load Diff
Vendored
+782
-576
File diff suppressed because it is too large
Load Diff
Vendored
+913
-749
File diff suppressed because it is too large
Load Diff
Vendored
+934
-711
File diff suppressed because it is too large
Load Diff
Vendored
+838
-629
File diff suppressed because it is too large
Load Diff
Vendored
+647
-455
File diff suppressed because it is too large
Load Diff
Vendored
+778
-569
File diff suppressed because it is too large
Load Diff
Vendored
+778
-567
File diff suppressed because it is too large
Load Diff
Vendored
+787
-575
File diff suppressed because it is too large
Load Diff
Vendored
+811
-599
File diff suppressed because it is too large
Load Diff
Vendored
+44
-26
@@ -6,18 +6,16 @@ list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/externals/find-modules")
|
||||
include(DownloadExternals)
|
||||
|
||||
# xbyak
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
add_subdirectory(xbyak)
|
||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||
add_subdirectory(xbyak EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# Dynarmic
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
if (ARCHITECTURE_arm64)
|
||||
set(DYNARMIC_FRONTENDS "A32")
|
||||
endif()
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||
set(DYNARMIC_NO_BUNDLED_FMT ON)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(dynarmic)
|
||||
add_subdirectory(dynarmic EXCLUDE_FROM_ALL)
|
||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||
endif()
|
||||
|
||||
# getopt
|
||||
@@ -29,7 +27,9 @@ endif()
|
||||
add_subdirectory(glad)
|
||||
|
||||
# inih
|
||||
add_subdirectory(inih)
|
||||
if (NOT TARGET inih::INIReader)
|
||||
add_subdirectory(inih)
|
||||
endif()
|
||||
|
||||
# mbedtls
|
||||
add_subdirectory(mbedtls EXCLUDE_FROM_ALL)
|
||||
@@ -45,8 +45,8 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12" AND CMAKE_CXX_COMPILER
|
||||
endif()
|
||||
|
||||
# libusb
|
||||
if (NOT LIBUSB_FOUND OR YUZU_USE_BUNDLED_LIBUSB)
|
||||
add_subdirectory(libusb)
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
# SDL2
|
||||
@@ -67,35 +67,46 @@ if (YUZU_USE_EXTERNAL_SDL2)
|
||||
endif()
|
||||
set(SDL_STATIC ON)
|
||||
set(SDL_SHARED OFF)
|
||||
if (APPLE)
|
||||
set(SDL_FILE ON)
|
||||
endif()
|
||||
|
||||
add_subdirectory(SDL EXCLUDE_FROM_ALL)
|
||||
add_library(SDL2 ALIAS SDL2-static)
|
||||
endif()
|
||||
|
||||
# ENet
|
||||
add_subdirectory(enet)
|
||||
target_include_directories(enet INTERFACE ./enet/include)
|
||||
if (NOT TARGET enet::enet)
|
||||
add_subdirectory(enet EXCLUDE_FROM_ALL)
|
||||
target_include_directories(enet INTERFACE ./enet/include)
|
||||
add_library(enet::enet ALIAS enet)
|
||||
endif()
|
||||
|
||||
# Cubeb
|
||||
if(ENABLE_CUBEB)
|
||||
if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb)
|
||||
set(BUILD_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
|
||||
add_library(cubeb::cubeb ALIAS cubeb)
|
||||
endif()
|
||||
|
||||
# DiscordRPC
|
||||
if (USE_DISCORD_PRESENCE)
|
||||
if (USE_DISCORD_PRESENCE AND NOT TARGET DiscordRPC::discord-rpc)
|
||||
add_subdirectory(discord-rpc EXCLUDE_FROM_ALL)
|
||||
target_include_directories(discord-rpc INTERFACE ./discord-rpc/include)
|
||||
add_library(DiscordRPC::discord-rpc ALIAS discord-rpc)
|
||||
endif()
|
||||
|
||||
# Sirit
|
||||
add_subdirectory(sirit)
|
||||
add_subdirectory(sirit EXCLUDE_FROM_ALL)
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(OpenSSL 1.1)
|
||||
if (OPENSSL_FOUND)
|
||||
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
|
||||
else()
|
||||
if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
|
||||
if (NOT WIN32)
|
||||
find_package(OpenSSL 1.1)
|
||||
if (OPENSSL_FOUND)
|
||||
set(OPENSSL_LIBRARIES OpenSSL::SSL OpenSSL::Crypto)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (WIN32 OR NOT OPENSSL_FOUND)
|
||||
# LibreSSL
|
||||
set(LIBRESSL_SKIP_INSTALL ON CACHE BOOL "")
|
||||
set(OPENSSLDIR "/etc/ssl/")
|
||||
@@ -115,18 +126,20 @@ if (ENABLE_WEB_SERVICE)
|
||||
if (WIN32)
|
||||
target_link_libraries(httplib INTERFACE crypt32 cryptui ws2_32)
|
||||
endif()
|
||||
|
||||
# cpp-jwt
|
||||
add_library(httplib::httplib ALIAS httplib)
|
||||
endif()
|
||||
|
||||
# cpp-jwt
|
||||
if (ENABLE_WEB_SERVICE AND NOT TARGET cpp-jwt::cpp-jwt)
|
||||
add_library(cpp-jwt INTERFACE)
|
||||
target_include_directories(cpp-jwt INTERFACE ./cpp-jwt/include)
|
||||
target_compile_definitions(cpp-jwt INTERFACE CPP_JWT_USE_VENDORED_NLOHMANN_JSON)
|
||||
add_library(cpp-jwt::cpp-jwt ALIAS cpp-jwt)
|
||||
endif()
|
||||
|
||||
# Opus
|
||||
if (YUZU_USE_BUNDLED_OPUS)
|
||||
if (NOT TARGET Opus::opus)
|
||||
add_subdirectory(opus EXCLUDE_FROM_ALL)
|
||||
else()
|
||||
find_package(Opus 1.3 REQUIRED)
|
||||
endif()
|
||||
|
||||
# FFMpeg
|
||||
@@ -137,3 +150,8 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
set(FFmpeg_LIBRARIES "${FFmpeg_LIBRARIES}" PARENT_SCOPE)
|
||||
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
|
||||
endif()
|
||||
|
||||
# Vulkan-Headers
|
||||
if (NOT TARGET Vulkan::Headers)
|
||||
add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
Vendored
+1
-1
Submodule externals/SDL updated: b424665e08...f17058b562
Vendored
+1
-1
Submodule externals/Vulkan-Headers updated: 33d4dd987f...2826791bed
Vendored
+1
-1
Submodule externals/dynarmic updated: 07c614f91b...bd570e093c
+27
@@ -0,0 +1,27 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_path(DiscordRPC_INCLUDE_DIR discord_rpc.h)
|
||||
|
||||
find_library(DiscordRPC_LIBRARY discord-rpc)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(DiscordRPC
|
||||
REQUIRED_VARS
|
||||
DiscordRPC_LIBRARY
|
||||
DiscordRPC_INCLUDE_DIR
|
||||
)
|
||||
|
||||
if (DiscordRPC_FOUND AND NOT TARGET DiscordRPC::discord-rpc)
|
||||
add_library(DiscordRPC::discord-rpc UNKNOWN IMPORTED)
|
||||
set_target_properties(DiscordRPC::discord-rpc PROPERTIES
|
||||
IMPORTED_LOCATION "${DiscordRPC_LIBRARY}"
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${DiscordRPC_INCLUDE_DIR}"
|
||||
)
|
||||
endif()
|
||||
|
||||
mark_as_advanced(
|
||||
DiscordRPC_INCLUDE_DIR
|
||||
DiscordRPC_LIBRARY
|
||||
)
|
||||
+8
@@ -185,3 +185,11 @@ foreach(c ${_FFmpeg_ALL_COMPONENTS})
|
||||
endforeach()
|
||||
unset(_FFmpeg_ALL_COMPONENTS)
|
||||
unset(_FFmpeg_REQUIRED_VARS)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(FFmpeg
|
||||
REQUIRED_VARS
|
||||
FFmpeg_LIBRARIES
|
||||
FFmpeg_INCLUDE_DIR
|
||||
HANDLE_COMPONENTS
|
||||
)
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2009 Michal Cihar <michal@cihar.com>
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# - Find libusb-1.0 library
|
||||
# This module defines
|
||||
# LIBUSB_INCLUDE_DIR, where to find bluetooth.h
|
||||
# LIBUSB_LIBRARIES, the libraries needed to use libusb-1.0.
|
||||
# LIBUSB_FOUND, If false, do not try to use libusb-1.0.
|
||||
#
|
||||
# vim: expandtab sw=4 ts=4 sts=4:
|
||||
|
||||
if(ANDROID)
|
||||
set(LIBUSB_FOUND FALSE CACHE INTERNAL "libusb-1.0 found")
|
||||
message(STATUS "libusb-1.0 not found.")
|
||||
elseif (NOT LIBUSB_FOUND)
|
||||
pkg_check_modules (LIBUSB_PKG libusb-1.0)
|
||||
|
||||
find_path(LIBUSB_INCLUDE_DIR NAMES libusb.h
|
||||
PATHS
|
||||
${LIBUSB_PKG_INCLUDE_DIRS}
|
||||
/usr/include/libusb-1.0
|
||||
/usr/include
|
||||
/usr/local/include/libusb-1.0
|
||||
/usr/local/include
|
||||
)
|
||||
|
||||
find_library(LIBUSB_LIBRARIES NAMES usb-1.0 usb
|
||||
PATHS
|
||||
${LIBUSB_PKG_LIBRARY_DIRS}
|
||||
/usr/lib
|
||||
/usr/local/lib
|
||||
)
|
||||
|
||||
if(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||
set(LIBUSB_FOUND TRUE CACHE INTERNAL "libusb-1.0 found")
|
||||
message(STATUS "Found libusb-1.0: ${LIBUSB_INCLUDE_DIR}, ${LIBUSB_LIBRARIES}")
|
||||
else(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||
set(LIBUSB_FOUND FALSE CACHE INTERNAL "libusb-1.0 found")
|
||||
message(STATUS "libusb-1.0 not found.")
|
||||
endif(LIBUSB_INCLUDE_DIR AND LIBUSB_LIBRARIES)
|
||||
|
||||
mark_as_advanced(LIBUSB_INCLUDE_DIR LIBUSB_LIBRARIES)
|
||||
endif ()
|
||||
|
||||
+8
-12
@@ -1,19 +1,15 @@
|
||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig)
|
||||
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(opus IMPORTED_TARGET GLOBAL opus)
|
||||
if (opus_FOUND)
|
||||
add_library(Opus::opus ALIAS PkgConfig::opus)
|
||||
endif()
|
||||
endif()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Opus
|
||||
REQUIRED_VARS
|
||||
opus_LINK_LIBRARIES
|
||||
opus_FOUND
|
||||
VERSION_VAR opus_VERSION
|
||||
REQUIRED_VARS OPUS_LINK_LIBRARIES
|
||||
VERSION_VAR OPUS_VERSION
|
||||
)
|
||||
|
||||
if (Opus_FOUND AND NOT TARGET Opus::opus)
|
||||
add_library(Opus::opus ALIAS PkgConfig::OPUS)
|
||||
endif()
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(enet
|
||||
REQUIRED_VARS ENET_LINK_LIBRARIES
|
||||
VERSION_VAR ENET_VERSION
|
||||
)
|
||||
|
||||
if (enet_FOUND AND NOT TARGET enet::enet)
|
||||
add_library(enet::enet ALIAS PkgConfig::ENET)
|
||||
endif()
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
# SPDX-FileCopyrightText: 2022 Andrea Pappacoda <andrea@pappacoda.it>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package(httplib QUIET CONFIG)
|
||||
if (httplib_FOUND)
|
||||
find_package_handle_standard_args(httplib CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
|
||||
find_package_handle_standard_args(httplib
|
||||
REQUIRED_VARS HTTPLIB_INCLUDEDIR
|
||||
VERSION_VAR HTTPLIB_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
if (httplib_FOUND AND NOT TARGET httplib::httplib)
|
||||
add_library(httplib::httplib ALIAS PkgConfig::HTTPLIB)
|
||||
endif()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(inih
|
||||
REQUIRED_VARS INIREADER_LINK_LIBRARIES
|
||||
VERSION_VAR INIREADER_VERSION
|
||||
)
|
||||
|
||||
if (inih_FOUND AND NOT TARGET inih::INIReader)
|
||||
add_library(inih::INIReader ALIAS PkgConfig::INIREADER)
|
||||
endif()
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb
|
||||
REQUIRED_VARS LIBUSB_LINK_LIBRARIES
|
||||
VERSION_VAR LIBUSB_VERSION
|
||||
)
|
||||
|
||||
if (libusb_FOUND AND NOT TARGET libusb::usb)
|
||||
add_library(libusb::usb ALIAS PkgConfig::LIBUSB)
|
||||
endif()
|
||||
Vendored
+20
-13
@@ -1,19 +1,26 @@
|
||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(liblz4 IMPORTED_TARGET GLOBAL liblz4)
|
||||
if (liblz4_FOUND)
|
||||
add_library(lz4::lz4 ALIAS PkgConfig::liblz4)
|
||||
endif()
|
||||
find_package(lz4 QUIET CONFIG)
|
||||
if (lz4_FOUND)
|
||||
find_package_handle_standard_args(lz4 CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
||||
find_package_handle_standard_args(lz4
|
||||
REQUIRED_VARS LZ4_LINK_LIBRARIES
|
||||
VERSION_VAR LZ4_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(lz4
|
||||
REQUIRED_VARS
|
||||
liblz4_LINK_LIBRARIES
|
||||
liblz4_FOUND
|
||||
VERSION_VAR liblz4_VERSION
|
||||
)
|
||||
if (lz4_FOUND AND NOT TARGET lz4::lz4)
|
||||
if (TARGET LZ4::lz4_shared)
|
||||
add_library(lz4::lz4 ALIAS LZ4::lz4_shared)
|
||||
elseif (TARGET LZ4::lz4_static)
|
||||
add_library(lz4::lz4 ALIAS LZ4::lz4_static)
|
||||
else()
|
||||
add_library(lz4::lz4 ALIAS PkgConfig::LZ4)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
+20
-13
@@ -1,19 +1,26 @@
|
||||
# SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig)
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(libzstd IMPORTED_TARGET GLOBAL libzstd)
|
||||
if (libzstd_FOUND)
|
||||
add_library(zstd::zstd ALIAS PkgConfig::libzstd)
|
||||
endif()
|
||||
find_package(zstd QUIET CONFIG)
|
||||
if (zstd_FOUND)
|
||||
find_package_handle_standard_args(zstd CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
|
||||
find_package_handle_standard_args(zstd
|
||||
REQUIRED_VARS ZSTD_LINK_LIBRARIES
|
||||
VERSION_VAR ZSTD_VERSION
|
||||
)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(zstd
|
||||
REQUIRED_VARS
|
||||
libzstd_LINK_LIBRARIES
|
||||
libzstd_FOUND
|
||||
VERSION_VAR libzstd_VERSION
|
||||
)
|
||||
if (zstd_FOUND AND NOT TARGET zstd::zstd)
|
||||
if (TARGET zstd::libzstd_shared)
|
||||
add_library(zstd::zstd ALIAS zstd::libzstd_shared)
|
||||
elseif (TARGET zstd::libzstd_static)
|
||||
add_library(zstd::zstd ALIAS zstd::libzstd_static)
|
||||
else()
|
||||
add_library(zstd::zstd ALIAS PkgConfig::ZSTD)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
Vendored
+2
-1
@@ -9,4 +9,5 @@ add_library(inih
|
||||
)
|
||||
|
||||
create_target_directory_groups(inih)
|
||||
target_include_directories(inih INTERFACE .)
|
||||
target_include_directories(inih INTERFACE inih/cpp)
|
||||
add_library(inih::INIReader ALIAS inih)
|
||||
|
||||
Vendored
+2
@@ -273,3 +273,5 @@ else() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
configure_file(config.h.in config.h)
|
||||
endif() # MINGW OR (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
|
||||
add_library(libusb::usb ALIAS usb)
|
||||
|
||||
Vendored
+1
-1
Submodule externals/sirit updated: aa292d5665...d7ad93a888
+4
-1
@@ -82,8 +82,9 @@ if (MSVC)
|
||||
/wd4324 # 'struct_name': structure was padded due to __declspec(align())
|
||||
)
|
||||
|
||||
if (USE_CCACHE)
|
||||
if (USE_CCACHE OR YUZU_USE_PRECOMPILED_HEADERS)
|
||||
# when caching, we need to use /Z7 to downgrade debug info to use an older but more cachable format
|
||||
# Precompiled headers are deleted if not using /Z7. See https://github.com/nanoant/CMakePCHCompiler/issues/21
|
||||
add_compile_options(/Z7)
|
||||
else()
|
||||
add_compile_options(/Zi)
|
||||
@@ -112,6 +113,8 @@ else()
|
||||
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wno-braced-scalar-init>
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wno-unused-private-field>
|
||||
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-braced-scalar-init>
|
||||
$<$<CXX_COMPILER_ID:AppleClang>:-Wno-unused-private-field>
|
||||
)
|
||||
|
||||
if (ARCHITECTURE_x86_64)
|
||||
|
||||
@@ -31,6 +31,7 @@ add_library(audio_core STATIC
|
||||
out/audio_out.h
|
||||
out/audio_out_system.cpp
|
||||
out/audio_out_system.h
|
||||
precompiled_headers.h
|
||||
renderer/adsp/adsp.cpp
|
||||
renderer/adsp/adsp.h
|
||||
renderer/adsp/audio_renderer.cpp
|
||||
@@ -218,14 +219,18 @@ endif()
|
||||
|
||||
target_link_libraries(audio_core PUBLIC common core)
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
target_link_libraries(audio_core PRIVATE dynarmic)
|
||||
target_link_libraries(audio_core PRIVATE dynarmic::dynarmic)
|
||||
endif()
|
||||
|
||||
if(ENABLE_CUBEB)
|
||||
target_link_libraries(audio_core PRIVATE cubeb)
|
||||
target_link_libraries(audio_core PRIVATE cubeb::cubeb)
|
||||
target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
|
||||
endif()
|
||||
if(ENABLE_SDL2)
|
||||
target_link_libraries(audio_core PRIVATE SDL2)
|
||||
target_link_libraries(audio_core PRIVATE SDL2::SDL2)
|
||||
target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
|
||||
endif()
|
||||
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(audio_core PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
|
||||
#include "audio_core/audio_event.h"
|
||||
#include "common/assert.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore {
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
#include "common/polyfill_thread.h"
|
||||
|
||||
#include "audio_core/audio_event.h"
|
||||
|
||||
union Result;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "common/polyfill_thread.h"
|
||||
|
||||
#include "audio_core/common/common.h"
|
||||
#include "audio_core/renderer/system_manager.h"
|
||||
#include "core/hle/service/audio/errors.h"
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/common_funcs.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore {
|
||||
constexpr u32 CurrentRevision = 11;
|
||||
|
||||
@@ -91,9 +91,10 @@ public:
|
||||
* @param core_timing - The CoreTiming instance
|
||||
* @param session - The device session
|
||||
*
|
||||
* @return Is the buffer was released.
|
||||
* @return If any buffer was released.
|
||||
*/
|
||||
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session) {
|
||||
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session,
|
||||
bool force) {
|
||||
std::scoped_lock l{lock};
|
||||
bool buffer_released{false};
|
||||
while (registered_count > 0) {
|
||||
@@ -103,7 +104,8 @@ public:
|
||||
}
|
||||
|
||||
// Check with the backend if this buffer can be released yet.
|
||||
if (!session.IsBufferConsumed(buffers[index])) {
|
||||
// If we're shutting down, we don't care if it's been played or not.
|
||||
if (!force && !session.IsBufferConsumed(buffers[index])) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,6 +73,12 @@ void DeviceSession::Stop() {
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSession::ClearBuffers() {
|
||||
if (stream) {
|
||||
stream->ClearQueue();
|
||||
}
|
||||
}
|
||||
|
||||
void DeviceSession::AppendBuffers(std::span<const AudioBuffer> buffers) const {
|
||||
for (const auto& buffer : buffers) {
|
||||
Sink::SinkBuffer new_buffer{
|
||||
|
||||
@@ -90,6 +90,11 @@ public:
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* Clear out the underlying audio buffers in the backend stream.
|
||||
*/
|
||||
void ClearBuffers();
|
||||
|
||||
/**
|
||||
* Set this device session's volume.
|
||||
*
|
||||
|
||||
@@ -23,7 +23,6 @@ System::~System() {
|
||||
void System::Finalize() {
|
||||
Stop();
|
||||
session->Finalize();
|
||||
buffer_event->Signal();
|
||||
}
|
||||
|
||||
void System::StartSession() {
|
||||
@@ -102,6 +101,10 @@ Result System::Stop() {
|
||||
if (state == State::Started) {
|
||||
session->Stop();
|
||||
session->SetVolume(0.0f);
|
||||
session->ClearBuffers();
|
||||
if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) {
|
||||
buffer_event->Signal();
|
||||
}
|
||||
state = State::Stopped;
|
||||
}
|
||||
|
||||
@@ -138,7 +141,7 @@ void System::RegisterBuffers() {
|
||||
}
|
||||
|
||||
void System::ReleaseBuffers() {
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
|
||||
|
||||
if (signal) {
|
||||
// Signal if any buffer was released, or if none are registered, we need more.
|
||||
|
||||
@@ -24,7 +24,6 @@ System::~System() {
|
||||
void System::Finalize() {
|
||||
Stop();
|
||||
session->Finalize();
|
||||
buffer_event->Signal();
|
||||
}
|
||||
|
||||
std::string_view System::GetDefaultOutputDeviceName() const {
|
||||
@@ -102,6 +101,10 @@ Result System::Stop() {
|
||||
if (state == State::Started) {
|
||||
session->Stop();
|
||||
session->SetVolume(0.0f);
|
||||
session->ClearBuffers();
|
||||
if (buffers.ReleaseBuffers(system.CoreTiming(), *session, true)) {
|
||||
buffer_event->Signal();
|
||||
}
|
||||
state = State::Stopped;
|
||||
}
|
||||
|
||||
@@ -138,7 +141,7 @@ void System::RegisterBuffers() {
|
||||
}
|
||||
|
||||
void System::ReleaseBuffers() {
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
|
||||
if (signal) {
|
||||
// Signal if any buffer was released, or if none are registered, we need more.
|
||||
buffer_event->Signal();
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_precompiled_headers.h"
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "audio_core/renderer/adsp/command_list_processor.h"
|
||||
#include "audio_core/renderer/command/effect/i3dl2_reverb.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "audio_core/renderer/adsp/command_list_processor.h"
|
||||
#include "audio_core/renderer/command/effect/reverb.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "audio_core/renderer/mix/mix_context.h"
|
||||
#include "audio_core/renderer/splitter/splitter_context.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ class CommandGenerator;
|
||||
*/
|
||||
class DetailAspect {
|
||||
public:
|
||||
DetailAspect() = default;
|
||||
DetailAspect(CommandGenerator& command_generator, PerformanceEntryType entry_type, s32 node_id,
|
||||
PerformanceDetailType detail_type);
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ class CommandGenerator;
|
||||
*/
|
||||
class EntryAspect {
|
||||
public:
|
||||
EntryAspect() = default;
|
||||
EntryAspect(CommandGenerator& command_generator, PerformanceEntryType type, s32 node_id);
|
||||
|
||||
/// Command generator the command will be generated into
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <ranges>
|
||||
|
||||
#include "audio_core/renderer/voice/voice_context.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
|
||||
|
||||
@@ -170,8 +170,8 @@ void SinkStream::ProcessAudioIn(std::span<const s16> input_buffer, std::size_t n
|
||||
|
||||
// Get the minimum frames available between the currently playing buffer, and the
|
||||
// amount we have left to fill
|
||||
size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played,
|
||||
num_frames - frames_written)};
|
||||
size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played,
|
||||
num_frames - frames_written)};
|
||||
|
||||
samples_buffer.Push(&input_buffer[frames_written * frame_size],
|
||||
frames_available * frame_size);
|
||||
@@ -241,8 +241,8 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
|
||||
|
||||
// Get the minimum frames available between the currently playing buffer, and the
|
||||
// amount we have left to fill
|
||||
size_t frames_available{std::min(playing_buffer.frames - playing_buffer.frames_played,
|
||||
num_frames - frames_written)};
|
||||
size_t frames_available{std::min<u64>(playing_buffer.frames - playing_buffer.frames_played,
|
||||
num_frames - frames_written)};
|
||||
|
||||
samples_buffer.Pop(&output_buffer[frames_written * frame_size],
|
||||
frames_available * frame_size);
|
||||
@@ -266,19 +266,20 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
|
||||
}
|
||||
|
||||
void SinkStream::Stall() {
|
||||
if (stalled) {
|
||||
std::scoped_lock lk{stall_guard};
|
||||
if (stalled_lock) {
|
||||
return;
|
||||
}
|
||||
stalled = true;
|
||||
system.StallProcesses();
|
||||
stalled_lock = system.StallProcesses();
|
||||
}
|
||||
|
||||
void SinkStream::Unstall() {
|
||||
if (!stalled) {
|
||||
std::scoped_lock lk{stall_guard};
|
||||
if (!stalled_lock) {
|
||||
return;
|
||||
}
|
||||
system.UnstallProcesses();
|
||||
stalled = false;
|
||||
stalled_lock.unlock();
|
||||
}
|
||||
|
||||
} // namespace AudioCore::Sink
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <span>
|
||||
#include <vector>
|
||||
|
||||
@@ -240,8 +241,8 @@ private:
|
||||
f32 system_volume{1.0f};
|
||||
/// Set via IAudioDevice service calls
|
||||
f32 device_volume{1.0f};
|
||||
/// True if coretiming has been stalled
|
||||
bool stalled{false};
|
||||
std::mutex stall_guard;
|
||||
std::unique_lock<std::mutex> stalled_lock;
|
||||
};
|
||||
|
||||
using SinkStreamPtr = std::unique_ptr<SinkStream>;
|
||||
|
||||
@@ -34,9 +34,8 @@ add_library(common STATIC
|
||||
bit_util.h
|
||||
cityhash.cpp
|
||||
cityhash.h
|
||||
cache_management.cpp
|
||||
cache_management.h
|
||||
common_funcs.h
|
||||
common_precompiled_headers.h
|
||||
common_types.h
|
||||
concepts.h
|
||||
div_ceil.h
|
||||
@@ -95,6 +94,7 @@ add_library(common STATIC
|
||||
param_package.h
|
||||
parent_of_member.h
|
||||
point.h
|
||||
precompiled_headers.h
|
||||
quaternion.h
|
||||
reader_writer_queue.h
|
||||
ring_buffer.h
|
||||
@@ -147,7 +147,7 @@ if(ARCHITECTURE_x86_64)
|
||||
x64/xbyak_abi.h
|
||||
x64/xbyak_util.h
|
||||
)
|
||||
target_link_libraries(common PRIVATE xbyak)
|
||||
target_link_libraries(common PRIVATE xbyak::xbyak)
|
||||
endif()
|
||||
|
||||
if (MSVC)
|
||||
@@ -172,14 +172,8 @@ endif()
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
|
||||
if (TARGET lz4::lz4)
|
||||
target_link_libraries(common PRIVATE lz4::lz4)
|
||||
else()
|
||||
target_link_libraries(common PRIVATE LZ4::lz4_shared)
|
||||
endif()
|
||||
if (TARGET zstd::zstd)
|
||||
target_link_libraries(common PRIVATE zstd::zstd)
|
||||
else()
|
||||
target_link_libraries(common PRIVATE
|
||||
$<IF:$<TARGET_EXISTS:zstd::libzstd_shared>,zstd::libzstd_shared,zstd::libzstd_static>)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd)
|
||||
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(common PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
+2
-2
@@ -69,7 +69,7 @@ void assert_fail_impl();
|
||||
#define ASSERT_OR_EXECUTE(_a_, _b_) \
|
||||
do { \
|
||||
ASSERT(_a_); \
|
||||
if (!(_a_)) { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
@@ -78,7 +78,7 @@ void assert_fail_impl();
|
||||
#define ASSERT_OR_EXECUTE_MSG(_a_, _b_, ...) \
|
||||
do { \
|
||||
ASSERT_MSG(_a_, __VA_ARGS__); \
|
||||
if (!(_a_)) { \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "alignment.h"
|
||||
#include "cache_management.h"
|
||||
#include "common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
|
||||
// Most cache operations are no-ops on x86
|
||||
|
||||
void DataCacheLineCleanByVAToPoU(void* start, size_t size) {}
|
||||
void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size) {}
|
||||
void DataCacheLineCleanByVAToPoC(void* start, size_t size) {}
|
||||
void DataCacheZeroByVA(void* start, size_t size) {
|
||||
std::memset(start, 0, size);
|
||||
}
|
||||
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
|
||||
// BS/DminLine is log2(cache size in words), we want size in bytes
|
||||
#define EXTRACT_DMINLINE(ctr_el0) (1 << ((((ctr_el0) >> 16) & 0xf) + 2))
|
||||
#define EXTRACT_BS(dczid_el0) (1 << (((dczid_el0)&0xf) + 2))
|
||||
|
||||
#define DEFINE_DC_OP(op_name, function_name) \
|
||||
void function_name(void* start, size_t size) { \
|
||||
size_t ctr_el0; \
|
||||
asm volatile("mrs %[ctr_el0], ctr_el0\n\t" : [ctr_el0] "=r"(ctr_el0)); \
|
||||
size_t cacheline_size = EXTRACT_DMINLINE(ctr_el0); \
|
||||
uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \
|
||||
uintptr_t va_end = va_start + size; \
|
||||
for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \
|
||||
asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define DEFINE_DC_OP_DCZID(op_name, function_name) \
|
||||
void function_name(void* start, size_t size) { \
|
||||
size_t dczid_el0; \
|
||||
asm volatile("mrs %[dczid_el0], dczid_el0\n\t" : [dczid_el0] "=r"(dczid_el0)); \
|
||||
size_t cacheline_size = EXTRACT_BS(dczid_el0); \
|
||||
uintptr_t va_start = reinterpret_cast<uintptr_t>(start); \
|
||||
uintptr_t va_end = va_start + size; \
|
||||
for (uintptr_t va = va_start; va < va_end; va += cacheline_size) { \
|
||||
asm volatile("dc " #op_name ", %[va]\n\t" : : [va] "r"(va) : "memory"); \
|
||||
} \
|
||||
}
|
||||
|
||||
DEFINE_DC_OP(cvau, DataCacheLineCleanByVAToPoU);
|
||||
DEFINE_DC_OP(civac, DataCacheLineCleanAndInvalidateByVAToPoC);
|
||||
DEFINE_DC_OP(cvac, DataCacheLineCleanByVAToPoC);
|
||||
DEFINE_DC_OP_DCZID(zva, DataCacheZeroByVA);
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace Common
|
||||
@@ -1,27 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "stdlib.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
// Data cache instructions enabled at EL0 by SCTLR_EL1.UCI.
|
||||
// VA = virtual address
|
||||
// PoC = point of coherency
|
||||
// PoU = point of unification
|
||||
|
||||
// dc cvau
|
||||
void DataCacheLineCleanByVAToPoU(void* start, size_t size);
|
||||
|
||||
// dc civac
|
||||
void DataCacheLineCleanAndInvalidateByVAToPoC(void* start, size_t size);
|
||||
|
||||
// dc cvac
|
||||
void DataCacheLineCleanByVAToPoC(void* start, size_t size);
|
||||
|
||||
// dc zva
|
||||
void DataCacheZeroByVA(void* start, size_t size);
|
||||
|
||||
} // namespace Common
|
||||
@@ -0,0 +1,14 @@
|
||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <array>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/common_types.h"
|
||||
@@ -1,6 +1,8 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/logging/log.h"
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#include <algorithm>
|
||||
|
||||
#include "common/fs/fs_util.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
|
||||
namespace Common::FS {
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "common/fs/fs.h"
|
||||
|
||||
+38
-3
@@ -8,6 +8,7 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include "common/logging/log.h"
|
||||
#include "common/param_package.h"
|
||||
#include "common/uuid.h"
|
||||
@@ -383,6 +384,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 +406,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 +435,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 +462,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
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <climits>
|
||||
#include <stop_token>
|
||||
#include <thread>
|
||||
|
||||
#include <fmt/format.h>
|
||||
@@ -18,6 +17,7 @@
|
||||
#include "common/fs/fs_paths.h"
|
||||
#include "common/fs/path_util.h"
|
||||
#include "common/literals.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/thread.h"
|
||||
|
||||
#include "common/logging/backend.h"
|
||||
|
||||
@@ -0,0 +1,530 @@
|
||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
//
|
||||
// TODO: remove this file when ranges are supported by all compilation targets
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
#include <version>
|
||||
|
||||
#ifndef __cpp_lib_ranges
|
||||
|
||||
namespace std {
|
||||
namespace ranges {
|
||||
|
||||
template <typename T>
|
||||
concept range = requires(T& t) {
|
||||
begin(t);
|
||||
end(t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept input_range = range<T>;
|
||||
|
||||
template <typename T>
|
||||
concept output_range = range<T>;
|
||||
|
||||
template <range R>
|
||||
using range_difference_t = ptrdiff_t;
|
||||
|
||||
//
|
||||
// find, find_if, find_if_not
|
||||
//
|
||||
|
||||
struct find_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value,
|
||||
Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(proj, *first) == value) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct find_if_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(pred, std::invoke(proj, *first))) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct find_if_not_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (!std::invoke(pred, std::invoke(proj, *first))) {
|
||||
return first;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr find_fn find;
|
||||
inline constexpr find_if_fn find_if;
|
||||
inline constexpr find_if_not_fn find_if_not;
|
||||
|
||||
//
|
||||
// any_of, all_of, none_of
|
||||
//
|
||||
|
||||
struct all_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if_not(first, last, std::ref(pred), std::ref(proj)) == last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct any_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) != last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct none_of_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
return ranges::find_if(first, last, std::ref(pred), std::ref(proj)) == last;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr bool operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr any_of_fn any_of;
|
||||
inline constexpr all_of_fn all_of;
|
||||
inline constexpr none_of_fn none_of;
|
||||
|
||||
//
|
||||
// count, count_if
|
||||
//
|
||||
|
||||
struct count_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity>
|
||||
constexpr ptrdiff_t operator()(Iterator first, Iterator last, const T& value,
|
||||
Proj proj = {}) const {
|
||||
ptrdiff_t counter = 0;
|
||||
for (; first != last; ++first)
|
||||
if (std::invoke(proj, *first) == value)
|
||||
++counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity>
|
||||
constexpr ptrdiff_t operator()(R&& r, const T& value, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct count_if_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred>
|
||||
constexpr ptrdiff_t operator()(Iterator first, Iterator last, Pred pred, Proj proj = {}) const {
|
||||
ptrdiff_t counter = 0;
|
||||
for (; first != last; ++first)
|
||||
if (std::invoke(pred, std::invoke(proj, *first)))
|
||||
++counter;
|
||||
return counter;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Pred>
|
||||
constexpr ptrdiff_t operator()(R&& r, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr count_fn count;
|
||||
inline constexpr count_if_fn count_if;
|
||||
|
||||
//
|
||||
// transform
|
||||
//
|
||||
|
||||
struct transform_fn {
|
||||
template <typename InputIterator, typename OutputIterator, typename F,
|
||||
typename Proj = std::identity>
|
||||
constexpr void operator()(InputIterator first1, InputIterator last1, OutputIterator result,
|
||||
F op, Proj proj = {}) const {
|
||||
for (; first1 != last1; ++first1, (void)++result) {
|
||||
*result = std::invoke(op, std::invoke(proj, *first1));
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator, typename F,
|
||||
typename Proj = std::identity>
|
||||
constexpr void operator()(R&& r, OutputIterator result, F op, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), result, std::ref(op), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr transform_fn transform;
|
||||
|
||||
//
|
||||
// sort
|
||||
//
|
||||
|
||||
struct sort_fn {
|
||||
template <typename Iterator, typename Comp = ranges::less, typename Proj = std::identity>
|
||||
constexpr void operator()(Iterator first, Iterator last, Comp comp = {}, Proj proj = {}) const {
|
||||
if (first == last)
|
||||
return;
|
||||
|
||||
Iterator last_iter = ranges::next(first, last);
|
||||
std::sort(first, last_iter,
|
||||
[&](auto& lhs, auto& rhs) { return comp(proj(lhs), proj(rhs)); });
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Comp = ranges::less, typename Proj = std::identity>
|
||||
constexpr void operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(comp), std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr sort_fn sort;
|
||||
|
||||
//
|
||||
// fill
|
||||
//
|
||||
|
||||
struct fill_fn {
|
||||
template <typename T, typename OutputIterator>
|
||||
constexpr OutputIterator operator()(OutputIterator first, OutputIterator last,
|
||||
const T& value) const {
|
||||
while (first != last) {
|
||||
*first++ = value;
|
||||
}
|
||||
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename T, ranges::output_range R>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value);
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr fill_fn fill;
|
||||
|
||||
//
|
||||
// for_each
|
||||
//
|
||||
|
||||
struct for_each_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Fun>
|
||||
constexpr void operator()(Iterator first, Iterator last, Fun f, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
std::invoke(f, std::invoke(proj, *first));
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Fun>
|
||||
constexpr void operator()(R&& r, Fun f, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(f), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr for_each_fn for_each;
|
||||
|
||||
//
|
||||
// min_element, max_element
|
||||
//
|
||||
|
||||
struct min_element_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
auto smallest = first;
|
||||
++first;
|
||||
for (; first != last; ++first) {
|
||||
if (!std::invoke(comp, std::invoke(proj, *smallest), std::invoke(proj, *first))) {
|
||||
smallest = first;
|
||||
}
|
||||
}
|
||||
return smallest;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct max_element_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last) {
|
||||
return last;
|
||||
}
|
||||
|
||||
auto largest = first;
|
||||
++first;
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(comp, std::invoke(proj, *largest), std::invoke(proj, *first))) {
|
||||
largest = first;
|
||||
}
|
||||
}
|
||||
return largest;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity, typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Comp comp = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr min_element_fn min_element;
|
||||
inline constexpr max_element_fn max_element;
|
||||
|
||||
//
|
||||
// replace, replace_if
|
||||
//
|
||||
|
||||
struct replace_fn {
|
||||
template <typename Iterator, typename T1, typename T2, typename Proj = std::identity>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T1& old_value,
|
||||
const T2& new_value, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (old_value == std::invoke(proj, *first)) {
|
||||
*first = new_value;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T1, typename T2, typename Proj = std::identity>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T1& old_value, const T2& new_value,
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), old_value, new_value, std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct replace_if_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity, typename Pred>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred, const T& new_value,
|
||||
Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (!!std::invoke(pred, std::invoke(proj, *first))) {
|
||||
*first = new_value;
|
||||
}
|
||||
}
|
||||
return std::move(first);
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity, typename Pred>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred, const T& new_value,
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(pred), new_value,
|
||||
std::move(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr replace_fn replace;
|
||||
inline constexpr replace_if_fn replace_if;
|
||||
|
||||
//
|
||||
// copy, copy_if
|
||||
//
|
||||
|
||||
struct copy_fn {
|
||||
template <typename InputIterator, typename OutputIterator>
|
||||
constexpr void operator()(InputIterator first, InputIterator last,
|
||||
OutputIterator result) const {
|
||||
for (; first != last; ++first, (void)++result) {
|
||||
*result = *first;
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator>
|
||||
constexpr void operator()(R&& r, OutputIterator result) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(result));
|
||||
}
|
||||
};
|
||||
|
||||
struct copy_if_fn {
|
||||
template <typename InputIterator, typename OutputIterator, typename Proj = std::identity,
|
||||
typename Pred>
|
||||
constexpr void operator()(InputIterator first, InputIterator last, OutputIterator result,
|
||||
Pred pred, Proj proj = {}) const {
|
||||
for (; first != last; ++first) {
|
||||
if (std::invoke(pred, std::invoke(proj, *first))) {
|
||||
*result = *first;
|
||||
++result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename OutputIterator, typename Proj = std::identity,
|
||||
typename Pred>
|
||||
constexpr void operator()(R&& r, OutputIterator result, Pred pred, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(result), std::ref(pred),
|
||||
std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr copy_fn copy;
|
||||
inline constexpr copy_if_fn copy_if;
|
||||
|
||||
//
|
||||
// generate
|
||||
//
|
||||
|
||||
struct generate_fn {
|
||||
template <typename Iterator, typename F>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, F gen) const {
|
||||
for (; first != last; *first = std::invoke(gen), ++first)
|
||||
;
|
||||
return first;
|
||||
}
|
||||
|
||||
template <typename R, std::copy_constructible F>
|
||||
requires std::invocable<F&> && ranges::output_range<R>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, F gen) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::move(gen));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr generate_fn generate;
|
||||
|
||||
//
|
||||
// lower_bound, upper_bound
|
||||
//
|
||||
|
||||
struct lower_bound_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
Iterator it;
|
||||
std::ptrdiff_t _count, _step;
|
||||
_count = std::distance(first, last);
|
||||
|
||||
while (_count > 0) {
|
||||
it = first;
|
||||
_step = _count / 2;
|
||||
ranges::advance(it, _step, last);
|
||||
if (comp(std::invoke(proj, *it), value)) {
|
||||
first = ++it;
|
||||
_count -= _step + 1;
|
||||
} else {
|
||||
_count = _step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
struct upper_bound_fn {
|
||||
template <typename Iterator, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
Iterator it;
|
||||
std::ptrdiff_t _count, _step;
|
||||
_count = std::distance(first, last);
|
||||
|
||||
while (_count > 0) {
|
||||
it = first;
|
||||
_step = _count / 2;
|
||||
ranges::advance(it, _step, last);
|
||||
if (!comp(value, std::invoke(proj, *it))) {
|
||||
first = ++it;
|
||||
_count -= _step + 1;
|
||||
} else {
|
||||
_count = _step;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename T, typename Proj = std::identity,
|
||||
typename Comp = ranges::less>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, const T& value, Comp comp = {},
|
||||
Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), value, std::ref(comp), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr lower_bound_fn lower_bound;
|
||||
inline constexpr upper_bound_fn upper_bound;
|
||||
|
||||
//
|
||||
// adjacent_find
|
||||
//
|
||||
|
||||
struct adjacent_find_fn {
|
||||
template <typename Iterator, typename Proj = std::identity, typename Pred = ranges::equal_to>
|
||||
constexpr Iterator operator()(Iterator first, Iterator last, Pred pred = {},
|
||||
Proj proj = {}) const {
|
||||
if (first == last)
|
||||
return first;
|
||||
auto _next = ranges::next(first);
|
||||
for (; _next != last; ++_next, ++first)
|
||||
if (std::invoke(pred, std::invoke(proj, *first), std::invoke(proj, *_next)))
|
||||
return first;
|
||||
return _next;
|
||||
}
|
||||
|
||||
template <ranges::input_range R, typename Proj = std::identity,
|
||||
typename Pred = ranges::equal_to>
|
||||
constexpr ranges::iterator_t<R> operator()(R&& r, Pred pred = {}, Proj proj = {}) const {
|
||||
return operator()(ranges::begin(r), ranges::end(r), std::ref(pred), std::ref(proj));
|
||||
}
|
||||
};
|
||||
|
||||
inline constexpr adjacent_find_fn adjacent_find;
|
||||
|
||||
} // namespace ranges
|
||||
} // namespace std
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,323 @@
|
||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
//
|
||||
// TODO: remove this file when jthread is supported by all compilation targets
|
||||
//
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <version>
|
||||
|
||||
#ifdef __cpp_lib_jthread
|
||||
|
||||
#include <stop_token>
|
||||
#include <thread>
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <typename Condvar, typename Lock, typename Pred>
|
||||
void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) {
|
||||
cv.wait(lock, token, std::move(pred));
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
#else
|
||||
|
||||
#include <atomic>
|
||||
#include <functional>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
|
||||
namespace std {
|
||||
namespace polyfill {
|
||||
|
||||
using stop_state_callbacks = list<function<void()>>;
|
||||
|
||||
class stop_state {
|
||||
public:
|
||||
stop_state() = default;
|
||||
~stop_state() = default;
|
||||
|
||||
bool request_stop() {
|
||||
stop_state_callbacks callbacks;
|
||||
|
||||
{
|
||||
scoped_lock lk{m_lock};
|
||||
|
||||
if (m_stop_requested.load()) {
|
||||
// Already set, nothing to do
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set as requested
|
||||
m_stop_requested = true;
|
||||
|
||||
// Copy callback list
|
||||
callbacks = m_callbacks;
|
||||
}
|
||||
|
||||
for (auto callback : callbacks) {
|
||||
callback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool stop_requested() const {
|
||||
return m_stop_requested.load();
|
||||
}
|
||||
|
||||
stop_state_callbacks::const_iterator insert_callback(function<void()> f) {
|
||||
stop_state_callbacks::const_iterator ret{};
|
||||
bool should_run{};
|
||||
|
||||
{
|
||||
scoped_lock lk{m_lock};
|
||||
should_run = m_stop_requested.load();
|
||||
m_callbacks.push_front(f);
|
||||
ret = m_callbacks.begin();
|
||||
}
|
||||
|
||||
if (should_run) {
|
||||
f();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void remove_callback(stop_state_callbacks::const_iterator it) {
|
||||
scoped_lock lk{m_lock};
|
||||
m_callbacks.erase(it);
|
||||
}
|
||||
|
||||
private:
|
||||
mutex m_lock;
|
||||
atomic<bool> m_stop_requested;
|
||||
stop_state_callbacks m_callbacks;
|
||||
};
|
||||
|
||||
} // namespace polyfill
|
||||
|
||||
class stop_token;
|
||||
class stop_source;
|
||||
struct nostopstate_t {
|
||||
explicit nostopstate_t() = default;
|
||||
};
|
||||
inline constexpr nostopstate_t nostopstate{};
|
||||
|
||||
template <class Callback>
|
||||
class stop_callback;
|
||||
|
||||
class stop_token {
|
||||
public:
|
||||
stop_token() noexcept = default;
|
||||
|
||||
stop_token(const stop_token&) noexcept = default;
|
||||
stop_token(stop_token&&) noexcept = default;
|
||||
stop_token& operator=(const stop_token&) noexcept = default;
|
||||
stop_token& operator=(stop_token&&) noexcept = default;
|
||||
~stop_token() = default;
|
||||
|
||||
void swap(stop_token& other) noexcept {
|
||||
m_stop_state.swap(other.m_stop_state);
|
||||
}
|
||||
|
||||
[[nodiscard]] bool stop_requested() const noexcept {
|
||||
return m_stop_state && m_stop_state->stop_requested();
|
||||
}
|
||||
[[nodiscard]] bool stop_possible() const noexcept {
|
||||
return m_stop_state != nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
friend class stop_source;
|
||||
template <typename Callback>
|
||||
friend class stop_callback;
|
||||
stop_token(shared_ptr<polyfill::stop_state> stop_state) : m_stop_state(move(stop_state)) {}
|
||||
|
||||
private:
|
||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||
};
|
||||
|
||||
class stop_source {
|
||||
public:
|
||||
stop_source() : m_stop_state(make_shared<polyfill::stop_state>()) {}
|
||||
explicit stop_source(nostopstate_t) noexcept {}
|
||||
|
||||
stop_source(const stop_source&) noexcept = default;
|
||||
stop_source(stop_source&&) noexcept = default;
|
||||
stop_source& operator=(const stop_source&) noexcept = default;
|
||||
stop_source& operator=(stop_source&&) noexcept = default;
|
||||
~stop_source() = default;
|
||||
void swap(stop_source& other) noexcept {
|
||||
m_stop_state.swap(other.m_stop_state);
|
||||
}
|
||||
|
||||
[[nodiscard]] stop_token get_token() const noexcept {
|
||||
return stop_token(m_stop_state);
|
||||
}
|
||||
[[nodiscard]] bool stop_possible() const noexcept {
|
||||
return m_stop_state != nullptr;
|
||||
}
|
||||
[[nodiscard]] bool stop_requested() const noexcept {
|
||||
return m_stop_state && m_stop_state->stop_requested();
|
||||
}
|
||||
bool request_stop() noexcept {
|
||||
return m_stop_state && m_stop_state->request_stop();
|
||||
}
|
||||
|
||||
private:
|
||||
friend class jthread;
|
||||
explicit stop_source(shared_ptr<polyfill::stop_state> stop_state)
|
||||
: m_stop_state(move(stop_state)) {}
|
||||
|
||||
private:
|
||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
class stop_callback {
|
||||
static_assert(is_nothrow_destructible_v<Callback>);
|
||||
static_assert(is_invocable_v<Callback>);
|
||||
|
||||
public:
|
||||
using callback_type = Callback;
|
||||
|
||||
template <typename C>
|
||||
requires constructible_from<Callback, C>
|
||||
explicit stop_callback(const stop_token& st,
|
||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||
: m_stop_state(st.m_stop_state) {
|
||||
if (m_stop_state) {
|
||||
m_callback = m_stop_state->insert_callback(move(cb));
|
||||
}
|
||||
}
|
||||
template <typename C>
|
||||
requires constructible_from<Callback, C>
|
||||
explicit stop_callback(stop_token&& st,
|
||||
C&& cb) noexcept(is_nothrow_constructible_v<Callback, C>)
|
||||
: m_stop_state(move(st.m_stop_state)) {
|
||||
if (m_stop_state) {
|
||||
m_callback = m_stop_state->insert_callback(move(cb));
|
||||
}
|
||||
}
|
||||
~stop_callback() {
|
||||
if (m_stop_state && m_callback) {
|
||||
m_stop_state->remove_callback(*m_callback);
|
||||
}
|
||||
}
|
||||
|
||||
stop_callback(const stop_callback&) = delete;
|
||||
stop_callback(stop_callback&&) = delete;
|
||||
stop_callback& operator=(const stop_callback&) = delete;
|
||||
stop_callback& operator=(stop_callback&&) = delete;
|
||||
|
||||
private:
|
||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||
optional<polyfill::stop_state_callbacks::const_iterator> m_callback;
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
stop_callback(stop_token, Callback) -> stop_callback<Callback>;
|
||||
|
||||
class jthread {
|
||||
public:
|
||||
using id = thread::id;
|
||||
using native_handle_type = thread::native_handle_type;
|
||||
|
||||
jthread() noexcept = default;
|
||||
|
||||
template <typename F, typename... Args,
|
||||
typename = enable_if_t<!is_same_v<remove_cvref_t<F>, jthread>>>
|
||||
explicit jthread(F&& f, Args&&... args)
|
||||
: m_stop_state(make_shared<polyfill::stop_state>()),
|
||||
m_thread(make_thread(move(f), move(args)...)) {}
|
||||
|
||||
~jthread() {
|
||||
if (joinable()) {
|
||||
request_stop();
|
||||
join();
|
||||
}
|
||||
}
|
||||
|
||||
jthread(const jthread&) = delete;
|
||||
jthread(jthread&&) noexcept = default;
|
||||
jthread& operator=(const jthread&) = delete;
|
||||
|
||||
jthread& operator=(jthread&& other) noexcept {
|
||||
m_thread.swap(other.m_thread);
|
||||
m_stop_state.swap(other.m_stop_state);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void swap(jthread& other) noexcept {
|
||||
m_thread.swap(other.m_thread);
|
||||
m_stop_state.swap(other.m_stop_state);
|
||||
}
|
||||
[[nodiscard]] bool joinable() const noexcept {
|
||||
return m_thread.joinable();
|
||||
}
|
||||
void join() {
|
||||
m_thread.join();
|
||||
}
|
||||
void detach() {
|
||||
m_thread.detach();
|
||||
m_stop_state.reset();
|
||||
}
|
||||
|
||||
[[nodiscard]] id get_id() const noexcept {
|
||||
return m_thread.get_id();
|
||||
}
|
||||
[[nodiscard]] native_handle_type native_handle() {
|
||||
return m_thread.native_handle();
|
||||
}
|
||||
[[nodiscard]] stop_source get_stop_source() noexcept {
|
||||
return stop_source(m_stop_state);
|
||||
}
|
||||
[[nodiscard]] stop_token get_stop_token() const noexcept {
|
||||
return stop_source(m_stop_state).get_token();
|
||||
}
|
||||
bool request_stop() noexcept {
|
||||
return get_stop_source().request_stop();
|
||||
}
|
||||
[[nodiscard]] static unsigned int hardware_concurrency() noexcept {
|
||||
return thread::hardware_concurrency();
|
||||
}
|
||||
|
||||
private:
|
||||
template <typename F, typename... Args>
|
||||
thread make_thread(F&& f, Args&&... args) {
|
||||
if constexpr (is_invocable_v<decay_t<F>, stop_token, decay_t<Args>...>) {
|
||||
return thread(move(f), get_stop_token(), move(args)...);
|
||||
} else {
|
||||
return thread(move(f), move(args)...);
|
||||
}
|
||||
}
|
||||
|
||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||
thread m_thread;
|
||||
};
|
||||
|
||||
} // namespace std
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <typename Condvar, typename Lock, typename Pred>
|
||||
void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) {
|
||||
if (token.stop_requested()) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::stop_callback callback(token, [&] { cv.notify_all(); });
|
||||
cv.wait(lock, [&] { return pred() || token.stop_requested(); });
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/common_precompiled_headers.h"
|
||||
@@ -40,6 +40,7 @@ void LogSettings() {
|
||||
LOG_INFO(Config, "yuzu Configuration:");
|
||||
log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue());
|
||||
log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0));
|
||||
log_setting("System_DeviceName", values.device_name.GetValue());
|
||||
log_setting("System_CurrentUser", values.current_user.GetValue());
|
||||
log_setting("System_LanguageIndex", values.language_index.GetValue());
|
||||
log_setting("System_RegionIndex", values.region_index.GetValue());
|
||||
@@ -48,6 +49,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 +183,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);
|
||||
|
||||
@@ -19,6 +19,7 @@ namespace Settings {
|
||||
enum class RendererBackend : u32 {
|
||||
OpenGL = 0,
|
||||
Vulkan = 1,
|
||||
Null = 2,
|
||||
};
|
||||
|
||||
enum class ShaderBackend : u32 {
|
||||
@@ -75,7 +76,8 @@ enum class ScalingFilter : u32 {
|
||||
enum class AntiAliasing : u32 {
|
||||
None = 0,
|
||||
Fxaa = 1,
|
||||
LastAA = Fxaa,
|
||||
Smaa = 2,
|
||||
LastAA = Smaa,
|
||||
};
|
||||
|
||||
struct ResolutionScalingInfo {
|
||||
@@ -399,6 +401,7 @@ struct Values {
|
||||
Setting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"};
|
||||
Setting<bool> cpuopt_fastmem_exclusives{true, "cpuopt_fastmem_exclusives"};
|
||||
Setting<bool> cpuopt_recompile_exclusives{true, "cpuopt_recompile_exclusives"};
|
||||
Setting<bool> cpuopt_ignore_memory_aborts{true, "cpuopt_ignore_memory_aborts"};
|
||||
|
||||
SwitchableSetting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"};
|
||||
SwitchableSetting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"};
|
||||
@@ -411,7 +414,7 @@ struct Values {
|
||||
|
||||
// Renderer
|
||||
SwitchableSetting<RendererBackend, true> renderer_backend{
|
||||
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Vulkan, "backend"};
|
||||
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"};
|
||||
Setting<bool> renderer_debug{false, "debug"};
|
||||
Setting<bool> renderer_shader_feedback{false, "shader_feedback"};
|
||||
Setting<bool> enable_nsight_aftermath{false, "nsight_aftermath"};
|
||||
@@ -421,6 +424,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 +446,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"};
|
||||
@@ -454,6 +458,7 @@ struct Values {
|
||||
|
||||
// System
|
||||
SwitchableSetting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"};
|
||||
Setting<std::string> device_name{"Yuzu", "device_name"};
|
||||
// Measured in seconds since epoch
|
||||
std::optional<s64> custom_rtc;
|
||||
// Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc`
|
||||
|
||||
@@ -391,6 +391,7 @@ struct PlayerInput {
|
||||
u32 body_color_right;
|
||||
u32 button_color_left;
|
||||
u32 button_color_right;
|
||||
std::string profile_name;
|
||||
};
|
||||
|
||||
struct TouchscreenInput {
|
||||
|
||||
@@ -141,7 +141,7 @@ static std::wstring CPToUTF16(u32 code_page, const std::string& input) {
|
||||
MultiByteToWideChar(code_page, 0, input.data(), static_cast<int>(input.size()), nullptr, 0);
|
||||
|
||||
if (size == 0) {
|
||||
return L"";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring output(size, L'\0');
|
||||
@@ -158,7 +158,7 @@ std::string UTF16ToUTF8(const std::wstring& input) {
|
||||
const auto size = WideCharToMultiByte(CP_UTF8, 0, input.data(), static_cast<int>(input.size()),
|
||||
nullptr, 0, nullptr, nullptr);
|
||||
if (size == 0) {
|
||||
return "";
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string output(size, '\0');
|
||||
|
||||
+7
-4
@@ -11,6 +11,7 @@
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
#include "common/common_types.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -69,7 +70,7 @@ public:
|
||||
explicit Barrier(std::size_t count_) : count(count_) {}
|
||||
|
||||
/// Blocks until all "count" threads have called Sync()
|
||||
void Sync() {
|
||||
bool Sync(std::stop_token token = {}) {
|
||||
std::unique_lock lk{mutex};
|
||||
const std::size_t current_generation = generation;
|
||||
|
||||
@@ -77,14 +78,16 @@ public:
|
||||
generation++;
|
||||
waiting = 0;
|
||||
condvar.notify_all();
|
||||
return true;
|
||||
} else {
|
||||
condvar.wait(lk,
|
||||
[this, current_generation] { return current_generation != generation; });
|
||||
CondvarWait(condvar, lk, token,
|
||||
[this, current_generation] { return current_generation != generation; });
|
||||
return !token.stop_requested();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::condition_variable condvar;
|
||||
std::condition_variable_any condvar;
|
||||
std::mutex mutex;
|
||||
std::size_t count;
|
||||
std::size_t waiting = 0;
|
||||
|
||||
@@ -7,13 +7,13 @@
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
#include <stop_token>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <vector>
|
||||
#include <queue>
|
||||
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/thread.h"
|
||||
#include "common/unique_function.h"
|
||||
|
||||
@@ -47,7 +47,8 @@ public:
|
||||
if (requests.empty()) {
|
||||
wait_condition.notify_all();
|
||||
}
|
||||
condition.wait(lock, stop_token, [this] { return !requests.empty(); });
|
||||
Common::CondvarWait(condition, lock, stop_token,
|
||||
[this] { return !requests.empty(); });
|
||||
if (stop_token.stop_requested()) {
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -12,6 +12,8 @@
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include "common/polyfill_thread.h"
|
||||
|
||||
namespace Common {
|
||||
template <typename T, bool with_stop_token = false>
|
||||
class SPSCQueue {
|
||||
@@ -97,7 +99,7 @@ public:
|
||||
T PopWait(std::stop_token stop_token) {
|
||||
if (Empty()) {
|
||||
std::unique_lock lock{cv_mutex};
|
||||
cv.wait(lock, stop_token, [this] { return !Empty(); });
|
||||
Common::CondvarWait(cv, lock, stop_token, [this] { return !Empty(); });
|
||||
}
|
||||
if (stop_token.stop_requested()) {
|
||||
return T{};
|
||||
|
||||
+13
-1
@@ -528,8 +528,15 @@ add_library(core STATIC
|
||||
hle/service/mnpp/mnpp_app.h
|
||||
hle/service/ncm/ncm.cpp
|
||||
hle/service/ncm/ncm.h
|
||||
hle/service/nfc/mifare_user.cpp
|
||||
hle/service/nfc/mifare_user.h
|
||||
hle/service/nfc/nfc.cpp
|
||||
hle/service/nfc/nfc.h
|
||||
hle/service/nfc/nfc_device.cpp
|
||||
hle/service/nfc/nfc_device.h
|
||||
hle/service/nfc/nfc_result.h
|
||||
hle/service/nfc/nfc_user.cpp
|
||||
hle/service/nfc/nfc_user.h
|
||||
hle/service/nfp/amiibo_crypto.cpp
|
||||
hle/service/nfp/amiibo_crypto.h
|
||||
hle/service/nfp/nfp.cpp
|
||||
@@ -766,6 +773,7 @@ add_library(core STATIC
|
||||
memory.h
|
||||
perf_stats.cpp
|
||||
perf_stats.h
|
||||
precompiled_headers.h
|
||||
reporter.cpp
|
||||
reporter.h
|
||||
telemetry_session.cpp
|
||||
@@ -818,5 +826,9 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
hle/service/jit/jit.cpp
|
||||
hle/service/jit/jit.h
|
||||
)
|
||||
target_link_libraries(core PRIVATE dynarmic)
|
||||
target_link_libraries(core PRIVATE dynarmic::dynarmic)
|
||||
endif()
|
||||
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(core PRIVATE precompiled_headers.h)
|
||||
endif()
|
||||
|
||||
@@ -145,11 +145,15 @@ void ARM_Interface::Run() {
|
||||
// Notify the debugger and go to sleep if a breakpoint was hit,
|
||||
// or if the thread is unable to continue for any reason.
|
||||
if (Has(hr, breakpoint) || Has(hr, no_execute)) {
|
||||
RewindBreakpointInstruction();
|
||||
if (!Has(hr, no_execute)) {
|
||||
RewindBreakpointInstruction();
|
||||
}
|
||||
if (system.DebuggerEnabled()) {
|
||||
system.GetDebugger().NotifyThreadStopped(current_thread);
|
||||
} else {
|
||||
LogBacktrace();
|
||||
}
|
||||
current_thread->RequestSuspend(Kernel::SuspendType::Debug);
|
||||
current_thread->RequestSuspend(SuspendType::Debug);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,9 @@ class DynarmicCallbacks32 : public Dynarmic::A32::UserCallbacks {
|
||||
public:
|
||||
explicit DynarmicCallbacks32(ARM_Dynarmic_32& parent_)
|
||||
: parent{parent_},
|
||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {}
|
||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
|
||||
check_memory_access{debugger_enabled ||
|
||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||
|
||||
u8 MemoryRead8(u32 vaddr) override {
|
||||
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
||||
@@ -154,6 +156,17 @@ public:
|
||||
}
|
||||
|
||||
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
|
||||
if (!check_memory_access) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!memory.IsValidVirtualAddressRange(addr, size)) {
|
||||
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
|
||||
addr);
|
||||
parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!debugger_enabled) {
|
||||
return true;
|
||||
}
|
||||
@@ -181,7 +194,8 @@ public:
|
||||
ARM_Dynarmic_32& parent;
|
||||
Core::Memory::Memory& memory;
|
||||
std::size_t num_interpreted_instructions{};
|
||||
bool debugger_enabled{};
|
||||
const bool debugger_enabled{};
|
||||
const bool check_memory_access{};
|
||||
static constexpr u64 minimum_run_cycles = 10000U;
|
||||
};
|
||||
|
||||
@@ -264,6 +278,9 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
|
||||
if (!Settings::values.cpuopt_recompile_exclusives) {
|
||||
config.recompile_on_exclusive_fastmem_failure = false;
|
||||
}
|
||||
if (!Settings::values.cpuopt_ignore_memory_aborts) {
|
||||
config.check_halt_on_memory_access = true;
|
||||
}
|
||||
} else {
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||
|
||||
@@ -29,7 +29,9 @@ class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
|
||||
public:
|
||||
explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent_)
|
||||
: parent{parent_},
|
||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()} {}
|
||||
memory(parent.system.Memory()), debugger_enabled{parent.system.DebuggerEnabled()},
|
||||
check_memory_access{debugger_enabled ||
|
||||
!Settings::values.cpuopt_ignore_memory_aborts.GetValue()} {}
|
||||
|
||||
u8 MemoryRead8(u64 vaddr) override {
|
||||
CheckMemoryAccess(vaddr, 1, Kernel::DebugWatchpointType::Read);
|
||||
@@ -198,6 +200,17 @@ public:
|
||||
}
|
||||
|
||||
bool CheckMemoryAccess(VAddr addr, u64 size, Kernel::DebugWatchpointType type) {
|
||||
if (!check_memory_access) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!memory.IsValidVirtualAddressRange(addr, size)) {
|
||||
LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}",
|
||||
addr);
|
||||
parent.jit.load()->HaltExecution(ARM_Interface::no_execute);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!debugger_enabled) {
|
||||
return true;
|
||||
}
|
||||
@@ -226,7 +239,8 @@ public:
|
||||
Core::Memory::Memory& memory;
|
||||
u64 tpidrro_el0 = 0;
|
||||
u64 tpidr_el0 = 0;
|
||||
bool debugger_enabled{};
|
||||
const bool debugger_enabled{};
|
||||
const bool check_memory_access{};
|
||||
static constexpr u64 minimum_run_cycles = 10000U;
|
||||
};
|
||||
|
||||
@@ -323,6 +337,9 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
|
||||
if (!Settings::values.cpuopt_recompile_exclusives) {
|
||||
config.recompile_on_exclusive_fastmem_failure = false;
|
||||
}
|
||||
if (!Settings::values.cpuopt_ignore_memory_aborts) {
|
||||
config.check_halt_on_memory_access = true;
|
||||
}
|
||||
} else {
|
||||
// Unsafe optimizations
|
||||
if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) {
|
||||
|
||||
+8
-7
@@ -189,7 +189,7 @@ struct System::Impl {
|
||||
|
||||
kernel.Suspend(false);
|
||||
core_timing.SyncPause(false);
|
||||
is_paused = false;
|
||||
is_paused.store(false, std::memory_order_relaxed);
|
||||
|
||||
return status;
|
||||
}
|
||||
@@ -200,14 +200,13 @@ struct System::Impl {
|
||||
|
||||
core_timing.SyncPause(true);
|
||||
kernel.Suspend(true);
|
||||
is_paused = true;
|
||||
is_paused.store(true, std::memory_order_relaxed);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool IsPaused() const {
|
||||
std::unique_lock lk(suspend_guard);
|
||||
return is_paused;
|
||||
return is_paused.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> StallProcesses() {
|
||||
@@ -218,7 +217,7 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
void UnstallProcesses() {
|
||||
if (!is_paused) {
|
||||
if (!IsPaused()) {
|
||||
core_timing.SyncPause(false);
|
||||
kernel.Suspend(false);
|
||||
}
|
||||
@@ -390,7 +389,9 @@ struct System::Impl {
|
||||
kernel.ShutdownCores();
|
||||
cpu_manager.Shutdown();
|
||||
debugger.reset();
|
||||
services->KillNVNFlinger();
|
||||
if (services) {
|
||||
services->KillNVNFlinger();
|
||||
}
|
||||
kernel.CloseServices();
|
||||
services.reset();
|
||||
service_manager.reset();
|
||||
@@ -465,7 +466,7 @@ struct System::Impl {
|
||||
}
|
||||
|
||||
mutable std::mutex suspend_guard;
|
||||
bool is_paused{};
|
||||
std::atomic_bool is_paused{};
|
||||
std::atomic<bool> is_shutting_down{};
|
||||
|
||||
Timing::CoreTiming core_timing;
|
||||
|
||||
@@ -20,23 +20,20 @@ namespace Core {
|
||||
CpuManager::CpuManager(System& system_) : system{system_} {}
|
||||
CpuManager::~CpuManager() = default;
|
||||
|
||||
void CpuManager::ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager,
|
||||
std::size_t core) {
|
||||
cpu_manager.RunThread(core);
|
||||
}
|
||||
|
||||
void CpuManager::Initialize() {
|
||||
num_cores = is_multicore ? Core::Hardware::NUM_CPU_CORES : 1;
|
||||
gpu_barrier = std::make_unique<Common::Barrier>(num_cores + 1);
|
||||
|
||||
for (std::size_t core = 0; core < num_cores; core++) {
|
||||
core_data[core].host_thread = std::jthread(ThreadStart, std::ref(*this), core);
|
||||
core_data[core].host_thread =
|
||||
std::jthread([this, core](std::stop_token token) { RunThread(token, core); });
|
||||
}
|
||||
}
|
||||
|
||||
void CpuManager::Shutdown() {
|
||||
for (std::size_t core = 0; core < num_cores; core++) {
|
||||
if (core_data[core].host_thread.joinable()) {
|
||||
core_data[core].host_thread.request_stop();
|
||||
core_data[core].host_thread.join();
|
||||
}
|
||||
}
|
||||
@@ -184,7 +181,7 @@ void CpuManager::ShutdownThread() {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
void CpuManager::RunThread(std::size_t core) {
|
||||
void CpuManager::RunThread(std::stop_token token, std::size_t core) {
|
||||
/// Initialization
|
||||
system.RegisterCoreThread(core);
|
||||
std::string name;
|
||||
@@ -206,7 +203,9 @@ void CpuManager::RunThread(std::size_t core) {
|
||||
});
|
||||
|
||||
// Running
|
||||
gpu_barrier->Sync();
|
||||
if (!gpu_barrier->Sync(token)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!is_async_gpu && !is_multicore) {
|
||||
system.GPU().ObtainContext();
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <thread>
|
||||
|
||||
#include "common/fiber.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/hardware_properties.h"
|
||||
|
||||
@@ -80,12 +81,10 @@ private:
|
||||
void SingleCoreRunGuestThread();
|
||||
void SingleCoreRunIdleThread();
|
||||
|
||||
static void ThreadStart(std::stop_token stop_token, CpuManager& cpu_manager, std::size_t core);
|
||||
|
||||
void GuestActivate();
|
||||
void HandleInterrupt();
|
||||
void ShutdownThread();
|
||||
void RunThread(std::size_t core);
|
||||
void RunThread(std::stop_token stop_token, std::size_t core);
|
||||
|
||||
struct CoreData {
|
||||
std::shared_ptr<Common::Fiber> host_context;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <boost/process/async_pipe.hpp>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/polyfill_thread.h"
|
||||
#include "common/thread.h"
|
||||
#include "core/core.h"
|
||||
#include "core/debugger/debugger.h"
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
#include <utility>
|
||||
|
||||
#include "common/logging/log.h"
|
||||
#include "common/polyfill_ranges.h"
|
||||
#include "core/crypto/aes_util.h"
|
||||
#include "core/crypto/ctr_encryption_layer.h"
|
||||
#include "core/crypto/key_manager.h"
|
||||
|
||||
@@ -16,7 +16,7 @@ DefaultControllerApplet::DefaultControllerApplet(HID::HIDCore& hid_core_) : hid_
|
||||
|
||||
DefaultControllerApplet::~DefaultControllerApplet() = default;
|
||||
|
||||
void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callback,
|
||||
void DefaultControllerApplet::ReconfigureControllers(ReconfigureCallback callback,
|
||||
const ControllerParameters& parameters) const {
|
||||
LOG_INFO(Service_HID, "called, deducing the best configuration based on the given parameters!");
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
@@ -35,9 +36,11 @@ struct ControllerParameters {
|
||||
|
||||
class ControllerApplet {
|
||||
public:
|
||||
using ReconfigureCallback = std::function<void()>;
|
||||
|
||||
virtual ~ControllerApplet();
|
||||
|
||||
virtual void ReconfigureControllers(std::function<void()> callback,
|
||||
virtual void ReconfigureControllers(ReconfigureCallback callback,
|
||||
const ControllerParameters& parameters) const = 0;
|
||||
};
|
||||
|
||||
@@ -46,7 +49,7 @@ public:
|
||||
explicit DefaultControllerApplet(HID::HIDCore& hid_core_);
|
||||
~DefaultControllerApplet() override;
|
||||
|
||||
void ReconfigureControllers(std::function<void()> callback,
|
||||
void ReconfigureControllers(ReconfigureCallback callback,
|
||||
const ControllerParameters& parameters) const override;
|
||||
|
||||
private:
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace Core::Frontend {
|
||||
|
||||
ErrorApplet::~ErrorApplet() = default;
|
||||
|
||||
void DefaultErrorApplet::ShowError(Result error, std::function<void()> finished) const {
|
||||
void DefaultErrorApplet::ShowError(Result error, FinishedCallback finished) const {
|
||||
LOG_CRITICAL(Service_Fatal, "Application requested error display: {:04}-{:04} (raw={:08X})",
|
||||
error.module.Value(), error.description.Value(), error.raw);
|
||||
}
|
||||
|
||||
void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::seconds time,
|
||||
std::function<void()> finished) const {
|
||||
FinishedCallback finished) const {
|
||||
LOG_CRITICAL(
|
||||
Service_Fatal,
|
||||
"Application requested error display: {:04X}-{:04X} (raw={:08X}) with timestamp={:016X}",
|
||||
@@ -23,7 +23,7 @@ void DefaultErrorApplet::ShowErrorWithTimestamp(Result error, std::chrono::secon
|
||||
|
||||
void DefaultErrorApplet::ShowCustomErrorText(Result error, std::string main_text,
|
||||
std::string detail_text,
|
||||
std::function<void()> finished) const {
|
||||
FinishedCallback finished) const {
|
||||
LOG_CRITICAL(Service_Fatal,
|
||||
"Application requested custom error with error_code={:04X}-{:04X} (raw={:08X})",
|
||||
error.module.Value(), error.description.Value(), error.raw);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user