Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9449b554ba |
@@ -11,7 +11,6 @@ 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" \
|
||||
|
||||
Executable → Regular
+1
-1
@@ -10,7 +10,7 @@ if grep -nrI '\s$' src *.yml *.txt *.md Doxyfile .gitignore .gitmodules .ci* dis
|
||||
fi
|
||||
|
||||
# Default clang-format points to default 3.5 version one
|
||||
CLANG_FORMAT=${CLANG_FORMAT:-clang-format-15}
|
||||
CLANG_FORMAT=clang-format-12
|
||||
$CLANG_FORMAT --version
|
||||
|
||||
if [ "$TRAVIS_EVENT_TYPE" = "pull_request" ]; then
|
||||
|
||||
@@ -12,7 +12,6 @@ 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" \
|
||||
|
||||
@@ -2,12 +2,15 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# Download all pull requests as patches that match a specific label
|
||||
# Usage: python apply-patches-by-label.py <Label to Match>
|
||||
# Usage: python download-patches-by-label.py <Label to Match> <Root Path Folder to DL to>
|
||||
|
||||
import json, requests, subprocess, sys, traceback
|
||||
import requests, sys, json, urllib3.request, shutil, subprocess, os, traceback
|
||||
|
||||
tagline = sys.argv[2]
|
||||
|
||||
http = urllib3.PoolManager()
|
||||
dl_list = {}
|
||||
|
||||
def check_individual(labels):
|
||||
for label in labels:
|
||||
if (label["name"] == sys.argv[1]):
|
||||
@@ -15,9 +18,8 @@ def check_individual(labels):
|
||||
return False
|
||||
|
||||
def do_page(page):
|
||||
url = f"https://api.github.com/repos/yuzu-emu/yuzu/pulls?page={page}"
|
||||
url = 'https://api.github.com/repos/yuzu-emu/yuzu/pulls?page=%s' % page
|
||||
response = requests.get(url)
|
||||
response.raise_for_status()
|
||||
if (response.ok):
|
||||
j = json.loads(response.content)
|
||||
if j == []:
|
||||
@@ -25,13 +27,13 @@ def do_page(page):
|
||||
for pr in j:
|
||||
if (check_individual(pr["labels"])):
|
||||
pn = pr["number"]
|
||||
print(f"Matched PR# {pn}")
|
||||
print(subprocess.check_output(["git", "fetch", "https://github.com/yuzu-emu/yuzu.git", f"pull/{pn}/head:pr-{pn}", "-f", "--no-recurse-submodules"]))
|
||||
print(subprocess.check_output(["git", "merge", "--squash", f"pr-{pn}"]))
|
||||
print(subprocess.check_output(["git", "commit", f"-m\"Merge {tagline} PR {pn}\""]))
|
||||
print("Matched PR# %s" % pn)
|
||||
print(subprocess.check_output(["git", "fetch", "https://github.com/yuzu-emu/yuzu.git", "pull/%s/head:pr-%s" % (pn, pn), "-f", "--no-recurse-submodules"]))
|
||||
print(subprocess.check_output(["git", "merge", "--squash", "pr-%s" % pn]))
|
||||
print(subprocess.check_output(["git", "commit", "-m\"Merge %s PR %s\"" % (tagline, pn)]))
|
||||
|
||||
try:
|
||||
for i in range(1,10):
|
||||
for i in range(1,30):
|
||||
do_page(i)
|
||||
except:
|
||||
traceback.print_exc(file=sys.stdout)
|
||||
|
||||
@@ -9,7 +9,7 @@ parameters:
|
||||
steps:
|
||||
- script: choco install vulkan-sdk
|
||||
displayName: 'Install vulkan-sdk'
|
||||
- script: refreshenv && mkdir build && cd build && cmake -E env CXXFLAGS="/Gw /GA /Gr /Ob2" cmake -G "Visual Studio 17 2022" -A x64 -DCMAKE_POLICY_DEFAULT_CMP0069=NEW -DYUZU_ENABLE_LTO=ON -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 -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 ..
|
||||
displayName: 'Configure CMake'
|
||||
- task: MSBuild@1
|
||||
displayName: 'Build'
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
[submodule "dynarmic"]
|
||||
path = externals/dynarmic
|
||||
url = https://github.com/MerryMage/dynarmic.git
|
||||
[submodule "libressl"]
|
||||
path = externals/libressl
|
||||
url = https://github.com/citra-emu/ext-libressl-portable.git
|
||||
[submodule "libusb"]
|
||||
path = externals/libusb/libusb
|
||||
url = https://github.com/libusb/libusb.git
|
||||
|
||||
+53
-40
@@ -3,14 +3,17 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(yuzu)
|
||||
# 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")
|
||||
|
||||
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/find-modules")
|
||||
include(DownloadExternals)
|
||||
include(CMakeDependentOption)
|
||||
include(CTest)
|
||||
|
||||
project(yuzu)
|
||||
|
||||
# Set bundled sdl2/qt as dependent options.
|
||||
# OFF by default, but if ENABLE_SDL2 and MSVC are true then ON
|
||||
@@ -19,8 +22,6 @@ 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_LIBUSB "Enable the use of LibUSB" ON)
|
||||
|
||||
option(ENABLE_OPENGL "Enable OpenGL" ON)
|
||||
mark_as_advanced(FORCE ENABLE_OPENGL)
|
||||
option(ENABLE_QT "Enable the Qt frontend" ON)
|
||||
@@ -34,8 +35,6 @@ option(ENABLE_WEB_SERVICE "Enable web services (telemetry, etc.)" ON)
|
||||
|
||||
option(YUZU_USE_BUNDLED_FFMPEG "Download/Build bundled FFmpeg" "${WIN32}")
|
||||
|
||||
option(YUZU_USE_EXTERNAL_VULKAN_HEADERS "Use Vulkan-Headers from externals" ON)
|
||||
|
||||
option(YUZU_USE_QT_MULTIMEDIA "Use QtMultimedia for Camera" OFF)
|
||||
|
||||
option(YUZU_USE_QT_WEB_ENGINE "Use QtWebEngine for web applet implementation" OFF)
|
||||
@@ -44,20 +43,16 @@ option(ENABLE_CUBEB "Enables the cubeb audio backend" ON)
|
||||
|
||||
option(USE_DISCORD_PRESENCE "Enables Discord Rich Presence" OFF)
|
||||
|
||||
option(YUZU_TESTS "Compile tests" "${BUILD_TESTING}")
|
||||
option(YUZU_TESTS "Compile tests" ON)
|
||||
|
||||
option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ON)
|
||||
|
||||
option(YUZU_ROOM "Compile LDN room server" 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)
|
||||
|
||||
option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF)
|
||||
|
||||
CMAKE_DEPENDENT_OPTION(YUZU_USE_FASTER_LD "Check if a faster linker is available" ON "NOT WIN32" OFF)
|
||||
|
||||
if (YUZU_USE_BUNDLED_VCPKG)
|
||||
@@ -67,9 +62,6 @@ if (YUZU_USE_BUNDLED_VCPKG)
|
||||
if (YUZU_CRASH_DUMPS)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "dbghelp")
|
||||
endif()
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
list(APPEND VCPKG_MANIFEST_FEATURES "web-service")
|
||||
endif()
|
||||
|
||||
include(${CMAKE_SOURCE_DIR}/externals/vcpkg/scripts/buildsystems/vcpkg.cmake)
|
||||
elseif(NOT "$ENV{VCPKG_TOOLCHAIN_FILE}" STREQUAL "")
|
||||
@@ -209,49 +201,53 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/bin)
|
||||
# System imported libraries
|
||||
# =======================================================================
|
||||
|
||||
# Enforce the search mode of non-required packages for better and shorter failure messages
|
||||
find_package(Boost 1.73.0 REQUIRED context)
|
||||
find_package(enet 1.3 MODULE)
|
||||
find_package(enet 1.3)
|
||||
find_package(fmt 9 REQUIRED)
|
||||
find_package(inih 52 MODULE COMPONENTS INIReader)
|
||||
find_package(LLVM MODULE COMPONENTS Demangle)
|
||||
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 MODULE)
|
||||
find_package(Opus 1.3)
|
||||
find_package(Vulkan 1.3.213)
|
||||
find_package(ZLIB 1.2 REQUIRED)
|
||||
find_package(zstd 1.5 REQUIRED)
|
||||
|
||||
if (NOT YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
find_package(Vulkan 1.3.238 REQUIRED)
|
||||
endif()
|
||||
|
||||
if (ENABLE_LIBUSB)
|
||||
find_package(libusb 1.0.24 MODULE)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
|
||||
find_package(xbyak 6 CONFIG)
|
||||
find_package(xbyak 6)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
find_package(dynarmic 6.4.0 CONFIG)
|
||||
find_package(dynarmic 6.4.0)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CUBEB)
|
||||
find_package(cubeb CONFIG)
|
||||
find_package(cubeb)
|
||||
endif()
|
||||
|
||||
if (USE_DISCORD_PRESENCE)
|
||||
find_package(DiscordRPC MODULE)
|
||||
find_package(DiscordRPC)
|
||||
endif()
|
||||
|
||||
if (ENABLE_WEB_SERVICE)
|
||||
find_package(cpp-jwt 1.4 CONFIG)
|
||||
find_package(httplib 0.12 MODULE COMPONENTS OpenSSL)
|
||||
find_package(cpp-jwt 1.4)
|
||||
find_package(httplib 0.11)
|
||||
endif()
|
||||
|
||||
if (YUZU_TESTS)
|
||||
find_package(Catch2 3.0.1 REQUIRED)
|
||||
find_package(Catch2 2.13.7 REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(Boost 1.73.0 COMPONENTS context)
|
||||
if (Boost_FOUND)
|
||||
set(Boost_LIBRARIES Boost::boost)
|
||||
# Conditionally add Boost::context only if the found Boost package provides it
|
||||
# The old version is missing Boost::context, so we want to avoid adding in that case
|
||||
# The new version requires adding Boost::context to prevent linking issues
|
||||
if (TARGET Boost::context)
|
||||
list(APPEND Boost_LIBRARIES Boost::context)
|
||||
endif()
|
||||
else()
|
||||
message(FATAL_ERROR "Boost 1.73.0 or newer not found")
|
||||
endif()
|
||||
|
||||
# boost:asio has functions that require AcceptEx et al
|
||||
@@ -264,11 +260,15 @@ if(ENABLE_QT6 AND Qt6_LOCATION)
|
||||
list(APPEND CMAKE_PREFIX_PATH "${Qt6_LOCATION}")
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(X11 REQUIRED)
|
||||
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)
|
||||
if (UNIX AND NOT APPLE)
|
||||
list(APPEND YUZU_QT_COMPONENTS2 DBus X11Extras)
|
||||
endif()
|
||||
if (YUZU_USE_QT_MULTIMEDIA)
|
||||
list(APPEND YUZU_QT_COMPONENTS2 Multimedia)
|
||||
@@ -450,6 +450,14 @@ if (ENABLE_SDL2)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Reexport some targets that are named differently when using the upstream CmakeConfig
|
||||
# In order to ALIAS targets to a new name, they first need to be IMPORTED_GLOBAL
|
||||
# Dynarmic checks for target `boost` and so we want to make sure it can find it through our system instead of using their external
|
||||
if (TARGET Boost::boost)
|
||||
set_target_properties(Boost::boost PROPERTIES IMPORTED_GLOBAL TRUE)
|
||||
add_library(boost ALIAS Boost::boost)
|
||||
endif()
|
||||
|
||||
# List of all FFmpeg components required
|
||||
set(FFmpeg_COMPONENTS
|
||||
avcodec
|
||||
@@ -499,7 +507,7 @@ endif()
|
||||
# against all the src files. This should be used before making a pull request.
|
||||
# =======================================================================
|
||||
|
||||
set(CLANG_FORMAT_POSTFIX "-15")
|
||||
set(CLANG_FORMAT_POSTFIX "-12")
|
||||
find_program(CLANG_FORMAT
|
||||
NAMES clang-format${CLANG_FORMAT_POSTFIX}
|
||||
clang-format
|
||||
@@ -565,7 +573,11 @@ function(create_target_directory_groups target_name)
|
||||
endfunction()
|
||||
|
||||
# Prevent boost from linking against libs when building
|
||||
target_link_libraries(Boost::headers INTERFACE Boost::disable_autolinking)
|
||||
add_definitions(-DBOOST_ERROR_CODE_HEADER_ONLY
|
||||
-DBOOST_SYSTEM_NO_LIB
|
||||
-DBOOST_DATE_TIME_NO_LIB
|
||||
-DBOOST_REGEX_NO_LIB
|
||||
)
|
||||
# Adjustments for MSVC + Ninja
|
||||
if (MSVC AND CMAKE_GENERATOR STREQUAL "Ninja")
|
||||
add_compile_options(
|
||||
@@ -590,6 +602,7 @@ if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
enable_testing()
|
||||
add_subdirectory(externals)
|
||||
add_subdirectory(src)
|
||||
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(LLVM QUIET COMPONENTS CONFIG)
|
||||
if (LLVM_FOUND)
|
||||
separate_arguments(LLVM_DEFINITIONS)
|
||||
if (LLVMDemangle IN_LIST LLVM_AVAILABLE_LIBS)
|
||||
set(LLVM_Demangle_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LLVM HANDLE_COMPONENTS CONFIG_MODE)
|
||||
|
||||
if (LLVM_FOUND AND LLVM_Demangle_FOUND AND NOT TARGET LLVM::Demangle)
|
||||
add_library(LLVM::Demangle INTERFACE IMPORTED)
|
||||
target_compile_definitions(LLVM::Demangle INTERFACE ${LLVM_DEFINITIONS})
|
||||
target_include_directories(LLVM::Demangle INTERFACE ${LLVM_INCLUDE_DIRS})
|
||||
# prefer shared LLVM: https://github.com/llvm/llvm-project/issues/34593
|
||||
# but use ugly hack because llvm_config doesn't support interface library
|
||||
add_library(_dummy_lib SHARED EXCLUDE_FROM_ALL src/yuzu/main.cpp)
|
||||
llvm_config(_dummy_lib USE_SHARED demangle)
|
||||
get_target_property(LLVM_LIBRARIES _dummy_lib LINK_LIBRARIES)
|
||||
target_link_libraries(LLVM::Demangle INTERFACE ${LLVM_LIBRARIES})
|
||||
endif()
|
||||
@@ -1,31 +0,0 @@
|
||||
# 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_CONSIDERED_CONFIGS)
|
||||
find_package_handle_standard_args(httplib HANDLE_COMPONENTS CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
|
||||
if ("-DCPPHTTPLIB_OPENSSL_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
|
||||
set(httplib_OpenSSL_FOUND TRUE)
|
||||
endif()
|
||||
if ("-DCPPHTTPLIB_ZLIB_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
|
||||
set(httplib_ZLIB_FOUND TRUE)
|
||||
endif()
|
||||
if ("-DCPPHTTPLIB_BROTLI_SUPPORT" IN_LIST HTTPLIB_CFLAGS_OTHER)
|
||||
set(httplib_Brotli_FOUND TRUE)
|
||||
endif()
|
||||
find_package_handle_standard_args(httplib
|
||||
REQUIRED_VARS HTTPLIB_INCLUDEDIR
|
||||
VERSION_VAR HTTPLIB_VERSION
|
||||
HANDLE_COMPONENTS
|
||||
)
|
||||
endif()
|
||||
|
||||
if (httplib_FOUND AND NOT TARGET httplib::httplib)
|
||||
add_library(httplib::httplib ALIAS PkgConfig::HTTPLIB)
|
||||
endif()
|
||||
@@ -1,27 +0,0 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(INIH QUIET IMPORTED_TARGET inih)
|
||||
if (INIReader IN_LIST inih_FIND_COMPONENTS)
|
||||
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
||||
if (INIREADER_FOUND)
|
||||
set(inih_INIReader_FOUND TRUE)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(inih
|
||||
REQUIRED_VARS INIH_LINK_LIBRARIES
|
||||
VERSION_VAR INIH_VERSION
|
||||
HANDLE_COMPONENTS
|
||||
)
|
||||
|
||||
if (inih_FOUND AND NOT TARGET inih::inih)
|
||||
add_library(inih::inih ALIAS PkgConfig::INIH)
|
||||
endif()
|
||||
|
||||
if (inih_FOUND AND inih_INIReader_FOUND AND NOT TARGET inih::INIReader)
|
||||
add_library(inih::INIReader ALIAS PkgConfig::INIREADER)
|
||||
endif()
|
||||
@@ -1,15 +0,0 @@
|
||||
---- LLVM Exceptions to the Apache 2.0 License ----
|
||||
|
||||
As an exception, if, as a result of your compiling your source code, portions
|
||||
of this Software are embedded into an Object form of such source code, you
|
||||
may redistribute such embedded portions in such Object form without complying
|
||||
with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
|
||||
|
||||
In addition, if you combine or link compiled forms of this Software with
|
||||
software that is licensed under the GPLv2 ("Combined Software") and if a
|
||||
court of competent jurisdiction determines that the patent provision (Section
|
||||
3), the indemnity provision (Section 9) or other Section of the License
|
||||
conflicts with the conditions of the GPLv2, you may retroactively and
|
||||
prospectively choose to deem waived or otherwise exclude such Section(s) of
|
||||
the License, but only in their entirety and only with respect to the Combined
|
||||
Software.
|
||||
Vendored
+704
-1057
File diff suppressed because it is too large
Load Diff
Vendored
+702
-1055
File diff suppressed because it is too large
Load Diff
Vendored
+701
-1054
File diff suppressed because it is too large
Load Diff
Vendored
+748
-1101
File diff suppressed because it is too large
Load Diff
Vendored
+706
-1059
File diff suppressed because it is too large
Load Diff
Vendored
+735
-1091
File diff suppressed because it is too large
Load Diff
Vendored
+712
-1068
File diff suppressed because it is too large
Load Diff
Vendored
+699
-1052
File diff suppressed because it is too large
Load Diff
Vendored
+768
-1120
File diff suppressed because it is too large
Load Diff
Vendored
+744
-1098
File diff suppressed because it is too large
Load Diff
Vendored
+707
-1063
File diff suppressed because it is too large
Load Diff
Vendored
+704
-1057
File diff suppressed because it is too large
Load Diff
Vendored
+702
-1055
File diff suppressed because it is too large
Load Diff
Vendored
+862
-1229
File diff suppressed because it is too large
Load Diff
Vendored
+876
-1235
File diff suppressed because it is too large
Load Diff
Vendored
+859
-1218
File diff suppressed because it is too large
Load Diff
Vendored
+820
-1182
File diff suppressed because it is too large
Load Diff
Vendored
+703
-1056
File diff suppressed because it is too large
Load Diff
Vendored
+711
-1068
File diff suppressed because it is too large
Load Diff
Vendored
+784
-1146
File diff suppressed because it is too large
Load Diff
Vendored
+467
-601
File diff suppressed because it is too large
Load Diff
Vendored
+467
-601
File diff suppressed because it is too large
Load Diff
Vendored
+745
-1101
File diff suppressed because it is too large
Load Diff
Vendored
+709
-1065
File diff suppressed because it is too large
Load Diff
Vendored
+5
-5
@@ -53,10 +53,10 @@ SPDX-License-Identifier: CC0-1.0
|
||||
<developer_name>yuzu Emulator Team</developer_name>
|
||||
<content_rating type="oars-1.0"/>
|
||||
<screenshots>
|
||||
<screenshot type="default"><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/001-Super%20Mario%20Odyssey%20.png</image></screenshot>
|
||||
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/004-The%20Legend%20of%20Zelda%20Skyward%20Sword%20HD.png</image></screenshot>
|
||||
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/007-Pokemon%20Sword.png</image></screenshot>
|
||||
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/010-Hyrule%20Warriors%20Age%20of%20Calamity.png</image></screenshot>
|
||||
<screenshot><image>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/039-Pok%C3%A9mon%20Mystery%20Dungeon%20Rescue%20Team%20DX.png.png.png</image></screenshot>
|
||||
<screenshot type="default">https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/001-Super%20Mario%20Odyssey%20.png</screenshot>
|
||||
<screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/004-The%20Legend%20of%20Zelda%20Skyward%20Sword%20HD.png</screenshot>
|
||||
<screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/007-Pokemon%20Sword.png</screenshot>
|
||||
<screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/010-Hyrule%20Warriors%20Age%20of%20Calamity.png</screenshot>
|
||||
<screenshot>https://raw.githubusercontent.com/yuzu-emu/yuzu-emu.github.io/master/images/screenshots/039-Pok%C3%A9mon%20Mystery%20Dungeon%20Rescue%20Team%20DX.png.png.png</screenshot>
|
||||
</screenshots>
|
||||
</component>
|
||||
|
||||
Vendored
+42
-26
@@ -1,12 +1,9 @@
|
||||
# SPDX-FileCopyrightText: 2016 Citra Emulator Project
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
# 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)
|
||||
|
||||
# Disable tests in all externals supporting the standard option name
|
||||
set(BUILD_TESTING OFF)
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/CMakeModules")
|
||||
list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/externals/find-modules")
|
||||
include(DownloadExternals)
|
||||
|
||||
# xbyak
|
||||
if ((ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) AND NOT TARGET xbyak::xbyak)
|
||||
@@ -15,7 +12,8 @@ endif()
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) AND NOT TARGET dynarmic::dynarmic)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON)
|
||||
set(DYNARMIC_NO_BUNDLED_FMT ON)
|
||||
set(DYNARMIC_IGNORE_ASSERTS ON CACHE BOOL "" FORCE)
|
||||
add_subdirectory(dynarmic EXCLUDE_FROM_ALL)
|
||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||
endif()
|
||||
@@ -47,7 +45,7 @@ if (CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12" AND CMAKE_CXX_COMPILER
|
||||
endif()
|
||||
|
||||
# libusb
|
||||
if (ENABLE_LIBUSB AND NOT TARGET libusb::usb)
|
||||
if (NOT TARGET libusb::usb)
|
||||
add_subdirectory(libusb EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
@@ -62,10 +60,10 @@ if (YUZU_USE_EXTERNAL_SDL2)
|
||||
Locale Power Render)
|
||||
foreach(_SUB ${SDL_UNUSED_SUBSYSTEMS})
|
||||
string(TOUPPER ${_SUB} _OPT)
|
||||
set(SDL_${_OPT} OFF)
|
||||
option(SDL_${_OPT} "" OFF)
|
||||
endforeach()
|
||||
|
||||
set(HIDAPI ON)
|
||||
option(HIDAPI "" ON)
|
||||
endif()
|
||||
set(SDL_STATIC ON)
|
||||
set(SDL_SHARED OFF)
|
||||
@@ -85,7 +83,7 @@ endif()
|
||||
|
||||
# Cubeb
|
||||
if (ENABLE_CUBEB AND NOT TARGET cubeb::cubeb)
|
||||
set(BUILD_TESTS OFF)
|
||||
set(BUILD_TESTS OFF CACHE BOOL "")
|
||||
add_subdirectory(cubeb EXCLUDE_FROM_ALL)
|
||||
add_library(cubeb::cubeb ALIAS cubeb)
|
||||
endif()
|
||||
@@ -100,18 +98,43 @@ endif()
|
||||
# Sirit
|
||||
add_subdirectory(sirit EXCLUDE_FROM_ALL)
|
||||
|
||||
# httplib
|
||||
if (ENABLE_WEB_SERVICE AND NOT TARGET httplib::httplib)
|
||||
set(HTTPLIB_REQUIRE_OPENSSL ON)
|
||||
add_subdirectory(cpp-httplib EXCLUDE_FROM_ALL)
|
||||
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/")
|
||||
add_subdirectory(libressl EXCLUDE_FROM_ALL)
|
||||
target_include_directories(ssl INTERFACE ./libressl/include)
|
||||
target_compile_definitions(ssl PRIVATE -DHAVE_INET_NTOP)
|
||||
get_directory_property(OPENSSL_LIBRARIES
|
||||
DIRECTORY libressl
|
||||
DEFINITION OPENSSL_LIBS)
|
||||
endif()
|
||||
|
||||
# httplib
|
||||
add_library(httplib INTERFACE)
|
||||
target_include_directories(httplib INTERFACE ./cpp-httplib)
|
||||
target_compile_definitions(httplib INTERFACE -DCPPHTTPLIB_OPENSSL_SUPPORT)
|
||||
target_link_libraries(httplib INTERFACE ${OPENSSL_LIBRARIES})
|
||||
if (WIN32)
|
||||
target_link_libraries(httplib INTERFACE crypt32 cryptui ws2_32)
|
||||
endif()
|
||||
add_library(httplib::httplib ALIAS httplib)
|
||||
endif()
|
||||
|
||||
# cpp-jwt
|
||||
if (ENABLE_WEB_SERVICE AND NOT TARGET cpp-jwt::cpp-jwt)
|
||||
set(CPP_JWT_BUILD_EXAMPLES OFF)
|
||||
set(CPP_JWT_BUILD_TESTS OFF)
|
||||
set(CPP_JWT_USE_VENDORED_NLOHMANN_JSON OFF)
|
||||
add_subdirectory(cpp-jwt EXCLUDE_FROM_ALL)
|
||||
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
|
||||
@@ -129,13 +152,6 @@ if (YUZU_USE_BUNDLED_FFMPEG)
|
||||
endif()
|
||||
|
||||
# Vulkan-Headers
|
||||
if (YUZU_USE_EXTERNAL_VULKAN_HEADERS)
|
||||
if (NOT TARGET Vulkan::Headers)
|
||||
add_subdirectory(Vulkan-Headers EXCLUDE_FROM_ALL)
|
||||
endif()
|
||||
|
||||
if (NOT TARGET LLVM::Demangle)
|
||||
add_library(demangle STATIC)
|
||||
target_include_directories(demangle PUBLIC ./demangle)
|
||||
target_sources(demangle PRIVATE demangle/ItaniumDemangle.cpp)
|
||||
add_library(LLVM::Demangle ALIAS demangle)
|
||||
endif()
|
||||
|
||||
Vendored
+1
-1
Submodule externals/Vulkan-Headers updated: 00671c64ba...2826791bed
Vendored
+1
-1
Submodule externals/cpp-httplib updated: 6d963fbe8d...305a7abcb9
-588
@@ -1,588 +0,0 @@
|
||||
//===------------------------- ItaniumDemangle.cpp ------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
// FIXME: (possibly) incomplete list of features that clang mangles that this
|
||||
// file does not yet support:
|
||||
// - C++ modules TS
|
||||
|
||||
#include "llvm/Demangle/Demangle.h"
|
||||
#include "llvm/Demangle/ItaniumDemangle.h"
|
||||
|
||||
#include <cassert>
|
||||
#include <cctype>
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <functional>
|
||||
#include <numeric>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
using namespace llvm;
|
||||
using namespace llvm::itanium_demangle;
|
||||
|
||||
constexpr const char *itanium_demangle::FloatData<float>::spec;
|
||||
constexpr const char *itanium_demangle::FloatData<double>::spec;
|
||||
constexpr const char *itanium_demangle::FloatData<long double>::spec;
|
||||
|
||||
// <discriminator> := _ <non-negative number> # when number < 10
|
||||
// := __ <non-negative number> _ # when number >= 10
|
||||
// extension := decimal-digit+ # at the end of string
|
||||
const char *itanium_demangle::parse_discriminator(const char *first,
|
||||
const char *last) {
|
||||
// parse but ignore discriminator
|
||||
if (first != last) {
|
||||
if (*first == '_') {
|
||||
const char *t1 = first + 1;
|
||||
if (t1 != last) {
|
||||
if (std::isdigit(*t1))
|
||||
first = t1 + 1;
|
||||
else if (*t1 == '_') {
|
||||
for (++t1; t1 != last && std::isdigit(*t1); ++t1)
|
||||
;
|
||||
if (t1 != last && *t1 == '_')
|
||||
first = t1 + 1;
|
||||
}
|
||||
}
|
||||
} else if (std::isdigit(*first)) {
|
||||
const char *t1 = first + 1;
|
||||
for (; t1 != last && std::isdigit(*t1); ++t1)
|
||||
;
|
||||
if (t1 == last)
|
||||
first = last;
|
||||
}
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
namespace {
|
||||
struct DumpVisitor {
|
||||
unsigned Depth = 0;
|
||||
bool PendingNewline = false;
|
||||
|
||||
template<typename NodeT> static constexpr bool wantsNewline(const NodeT *) {
|
||||
return true;
|
||||
}
|
||||
static bool wantsNewline(NodeArray A) { return !A.empty(); }
|
||||
static constexpr bool wantsNewline(...) { return false; }
|
||||
|
||||
template<typename ...Ts> static bool anyWantNewline(Ts ...Vs) {
|
||||
for (bool B : {wantsNewline(Vs)...})
|
||||
if (B)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void printStr(const char *S) { fprintf(stderr, "%s", S); }
|
||||
void print(StringView SV) {
|
||||
fprintf(stderr, "\"%.*s\"", (int)SV.size(), SV.begin());
|
||||
}
|
||||
void print(const Node *N) {
|
||||
if (N)
|
||||
N->visit(std::ref(*this));
|
||||
else
|
||||
printStr("<null>");
|
||||
}
|
||||
void print(NodeOrString NS) {
|
||||
if (NS.isNode())
|
||||
print(NS.asNode());
|
||||
else if (NS.isString())
|
||||
print(NS.asString());
|
||||
else
|
||||
printStr("NodeOrString()");
|
||||
}
|
||||
void print(NodeArray A) {
|
||||
++Depth;
|
||||
printStr("{");
|
||||
bool First = true;
|
||||
for (const Node *N : A) {
|
||||
if (First)
|
||||
print(N);
|
||||
else
|
||||
printWithComma(N);
|
||||
First = false;
|
||||
}
|
||||
printStr("}");
|
||||
--Depth;
|
||||
}
|
||||
|
||||
// Overload used when T is exactly 'bool', not merely convertible to 'bool'.
|
||||
void print(bool B) { printStr(B ? "true" : "false"); }
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_unsigned<T>::value>::type print(T N) {
|
||||
fprintf(stderr, "%llu", (unsigned long long)N);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
typename std::enable_if<std::is_signed<T>::value>::type print(T N) {
|
||||
fprintf(stderr, "%lld", (long long)N);
|
||||
}
|
||||
|
||||
void print(ReferenceKind RK) {
|
||||
switch (RK) {
|
||||
case ReferenceKind::LValue:
|
||||
return printStr("ReferenceKind::LValue");
|
||||
case ReferenceKind::RValue:
|
||||
return printStr("ReferenceKind::RValue");
|
||||
}
|
||||
}
|
||||
void print(FunctionRefQual RQ) {
|
||||
switch (RQ) {
|
||||
case FunctionRefQual::FrefQualNone:
|
||||
return printStr("FunctionRefQual::FrefQualNone");
|
||||
case FunctionRefQual::FrefQualLValue:
|
||||
return printStr("FunctionRefQual::FrefQualLValue");
|
||||
case FunctionRefQual::FrefQualRValue:
|
||||
return printStr("FunctionRefQual::FrefQualRValue");
|
||||
}
|
||||
}
|
||||
void print(Qualifiers Qs) {
|
||||
if (!Qs) return printStr("QualNone");
|
||||
struct QualName { Qualifiers Q; const char *Name; } Names[] = {
|
||||
{QualConst, "QualConst"},
|
||||
{QualVolatile, "QualVolatile"},
|
||||
{QualRestrict, "QualRestrict"},
|
||||
};
|
||||
for (QualName Name : Names) {
|
||||
if (Qs & Name.Q) {
|
||||
printStr(Name.Name);
|
||||
Qs = Qualifiers(Qs & ~Name.Q);
|
||||
if (Qs) printStr(" | ");
|
||||
}
|
||||
}
|
||||
}
|
||||
void print(SpecialSubKind SSK) {
|
||||
switch (SSK) {
|
||||
case SpecialSubKind::allocator:
|
||||
return printStr("SpecialSubKind::allocator");
|
||||
case SpecialSubKind::basic_string:
|
||||
return printStr("SpecialSubKind::basic_string");
|
||||
case SpecialSubKind::string:
|
||||
return printStr("SpecialSubKind::string");
|
||||
case SpecialSubKind::istream:
|
||||
return printStr("SpecialSubKind::istream");
|
||||
case SpecialSubKind::ostream:
|
||||
return printStr("SpecialSubKind::ostream");
|
||||
case SpecialSubKind::iostream:
|
||||
return printStr("SpecialSubKind::iostream");
|
||||
}
|
||||
}
|
||||
void print(TemplateParamKind TPK) {
|
||||
switch (TPK) {
|
||||
case TemplateParamKind::Type:
|
||||
return printStr("TemplateParamKind::Type");
|
||||
case TemplateParamKind::NonType:
|
||||
return printStr("TemplateParamKind::NonType");
|
||||
case TemplateParamKind::Template:
|
||||
return printStr("TemplateParamKind::Template");
|
||||
}
|
||||
}
|
||||
|
||||
void newLine() {
|
||||
printStr("\n");
|
||||
for (unsigned I = 0; I != Depth; ++I)
|
||||
printStr(" ");
|
||||
PendingNewline = false;
|
||||
}
|
||||
|
||||
template<typename T> void printWithPendingNewline(T V) {
|
||||
print(V);
|
||||
if (wantsNewline(V))
|
||||
PendingNewline = true;
|
||||
}
|
||||
|
||||
template<typename T> void printWithComma(T V) {
|
||||
if (PendingNewline || wantsNewline(V)) {
|
||||
printStr(",");
|
||||
newLine();
|
||||
} else {
|
||||
printStr(", ");
|
||||
}
|
||||
|
||||
printWithPendingNewline(V);
|
||||
}
|
||||
|
||||
struct CtorArgPrinter {
|
||||
DumpVisitor &Visitor;
|
||||
|
||||
template<typename T, typename ...Rest> void operator()(T V, Rest ...Vs) {
|
||||
if (Visitor.anyWantNewline(V, Vs...))
|
||||
Visitor.newLine();
|
||||
Visitor.printWithPendingNewline(V);
|
||||
int PrintInOrder[] = { (Visitor.printWithComma(Vs), 0)..., 0 };
|
||||
(void)PrintInOrder;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename NodeT> void operator()(const NodeT *Node) {
|
||||
Depth += 2;
|
||||
fprintf(stderr, "%s(", itanium_demangle::NodeKind<NodeT>::name());
|
||||
Node->match(CtorArgPrinter{*this});
|
||||
fprintf(stderr, ")");
|
||||
Depth -= 2;
|
||||
}
|
||||
|
||||
void operator()(const ForwardTemplateReference *Node) {
|
||||
Depth += 2;
|
||||
fprintf(stderr, "ForwardTemplateReference(");
|
||||
if (Node->Ref && !Node->Printing) {
|
||||
Node->Printing = true;
|
||||
CtorArgPrinter{*this}(Node->Ref);
|
||||
Node->Printing = false;
|
||||
} else {
|
||||
CtorArgPrinter{*this}(Node->Index);
|
||||
}
|
||||
fprintf(stderr, ")");
|
||||
Depth -= 2;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
void itanium_demangle::Node::dump() const {
|
||||
DumpVisitor V;
|
||||
visit(std::ref(V));
|
||||
V.newLine();
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
class BumpPointerAllocator {
|
||||
struct BlockMeta {
|
||||
BlockMeta* Next;
|
||||
size_t Current;
|
||||
};
|
||||
|
||||
static constexpr size_t AllocSize = 4096;
|
||||
static constexpr size_t UsableAllocSize = AllocSize - sizeof(BlockMeta);
|
||||
|
||||
alignas(long double) char InitialBuffer[AllocSize];
|
||||
BlockMeta* BlockList = nullptr;
|
||||
|
||||
void grow() {
|
||||
char* NewMeta = static_cast<char *>(std::malloc(AllocSize));
|
||||
if (NewMeta == nullptr)
|
||||
std::terminate();
|
||||
BlockList = new (NewMeta) BlockMeta{BlockList, 0};
|
||||
}
|
||||
|
||||
void* allocateMassive(size_t NBytes) {
|
||||
NBytes += sizeof(BlockMeta);
|
||||
BlockMeta* NewMeta = reinterpret_cast<BlockMeta*>(std::malloc(NBytes));
|
||||
if (NewMeta == nullptr)
|
||||
std::terminate();
|
||||
BlockList->Next = new (NewMeta) BlockMeta{BlockList->Next, 0};
|
||||
return static_cast<void*>(NewMeta + 1);
|
||||
}
|
||||
|
||||
public:
|
||||
BumpPointerAllocator()
|
||||
: BlockList(new (InitialBuffer) BlockMeta{nullptr, 0}) {}
|
||||
|
||||
void* allocate(size_t N) {
|
||||
N = (N + 15u) & ~15u;
|
||||
if (N + BlockList->Current >= UsableAllocSize) {
|
||||
if (N > UsableAllocSize)
|
||||
return allocateMassive(N);
|
||||
grow();
|
||||
}
|
||||
BlockList->Current += N;
|
||||
return static_cast<void*>(reinterpret_cast<char*>(BlockList + 1) +
|
||||
BlockList->Current - N);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
while (BlockList) {
|
||||
BlockMeta* Tmp = BlockList;
|
||||
BlockList = BlockList->Next;
|
||||
if (reinterpret_cast<char*>(Tmp) != InitialBuffer)
|
||||
std::free(Tmp);
|
||||
}
|
||||
BlockList = new (InitialBuffer) BlockMeta{nullptr, 0};
|
||||
}
|
||||
|
||||
~BumpPointerAllocator() { reset(); }
|
||||
};
|
||||
|
||||
class DefaultAllocator {
|
||||
BumpPointerAllocator Alloc;
|
||||
|
||||
public:
|
||||
void reset() { Alloc.reset(); }
|
||||
|
||||
template<typename T, typename ...Args> T *makeNode(Args &&...args) {
|
||||
return new (Alloc.allocate(sizeof(T)))
|
||||
T(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
void *allocateNodeArray(size_t sz) {
|
||||
return Alloc.allocate(sizeof(Node *) * sz);
|
||||
}
|
||||
};
|
||||
} // unnamed namespace
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Code beyond this point should not be synchronized with libc++abi.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
using Demangler = itanium_demangle::ManglingParser<DefaultAllocator>;
|
||||
|
||||
char *llvm::itaniumDemangle(const char *MangledName, char *Buf,
|
||||
size_t *N, int *Status) {
|
||||
if (MangledName == nullptr || (Buf != nullptr && N == nullptr)) {
|
||||
if (Status)
|
||||
*Status = demangle_invalid_args;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
int InternalStatus = demangle_success;
|
||||
Demangler Parser(MangledName, MangledName + std::strlen(MangledName));
|
||||
OutputStream S;
|
||||
|
||||
Node *AST = Parser.parse();
|
||||
|
||||
if (AST == nullptr)
|
||||
InternalStatus = demangle_invalid_mangled_name;
|
||||
else if (!initializeOutputStream(Buf, N, S, 1024))
|
||||
InternalStatus = demangle_memory_alloc_failure;
|
||||
else {
|
||||
assert(Parser.ForwardTemplateRefs.empty());
|
||||
AST->print(S);
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
Buf = S.getBuffer();
|
||||
}
|
||||
|
||||
if (Status)
|
||||
*Status = InternalStatus;
|
||||
return InternalStatus == demangle_success ? Buf : nullptr;
|
||||
}
|
||||
|
||||
ItaniumPartialDemangler::ItaniumPartialDemangler()
|
||||
: RootNode(nullptr), Context(new Demangler{nullptr, nullptr}) {}
|
||||
|
||||
ItaniumPartialDemangler::~ItaniumPartialDemangler() {
|
||||
delete static_cast<Demangler *>(Context);
|
||||
}
|
||||
|
||||
ItaniumPartialDemangler::ItaniumPartialDemangler(
|
||||
ItaniumPartialDemangler &&Other)
|
||||
: RootNode(Other.RootNode), Context(Other.Context) {
|
||||
Other.Context = Other.RootNode = nullptr;
|
||||
}
|
||||
|
||||
ItaniumPartialDemangler &ItaniumPartialDemangler::
|
||||
operator=(ItaniumPartialDemangler &&Other) {
|
||||
std::swap(RootNode, Other.RootNode);
|
||||
std::swap(Context, Other.Context);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// Demangle MangledName into an AST, storing it into this->RootNode.
|
||||
bool ItaniumPartialDemangler::partialDemangle(const char *MangledName) {
|
||||
Demangler *Parser = static_cast<Demangler *>(Context);
|
||||
size_t Len = std::strlen(MangledName);
|
||||
Parser->reset(MangledName, MangledName + Len);
|
||||
RootNode = Parser->parse();
|
||||
return RootNode == nullptr;
|
||||
}
|
||||
|
||||
static char *printNode(const Node *RootNode, char *Buf, size_t *N) {
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
RootNode->print(S);
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionBaseName(char *Buf, size_t *N) const {
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
|
||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||
|
||||
while (true) {
|
||||
switch (Name->getKind()) {
|
||||
case Node::KAbiTagAttr:
|
||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||
continue;
|
||||
case Node::KStdQualifiedName:
|
||||
Name = static_cast<const StdQualifiedName *>(Name)->Child;
|
||||
continue;
|
||||
case Node::KNestedName:
|
||||
Name = static_cast<const NestedName *>(Name)->Name;
|
||||
continue;
|
||||
case Node::KLocalName:
|
||||
Name = static_cast<const LocalName *>(Name)->Entity;
|
||||
continue;
|
||||
case Node::KNameWithTemplateArgs:
|
||||
Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
|
||||
continue;
|
||||
default:
|
||||
return printNode(Name, Buf, N);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionDeclContextName(char *Buf,
|
||||
size_t *N) const {
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
const Node *Name = static_cast<const FunctionEncoding *>(RootNode)->getName();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
|
||||
KeepGoingLocalFunction:
|
||||
while (true) {
|
||||
if (Name->getKind() == Node::KAbiTagAttr) {
|
||||
Name = static_cast<const AbiTagAttr *>(Name)->Base;
|
||||
continue;
|
||||
}
|
||||
if (Name->getKind() == Node::KNameWithTemplateArgs) {
|
||||
Name = static_cast<const NameWithTemplateArgs *>(Name)->Name;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
switch (Name->getKind()) {
|
||||
case Node::KStdQualifiedName:
|
||||
S += "std";
|
||||
break;
|
||||
case Node::KNestedName:
|
||||
static_cast<const NestedName *>(Name)->Qual->print(S);
|
||||
break;
|
||||
case Node::KLocalName: {
|
||||
auto *LN = static_cast<const LocalName *>(Name);
|
||||
LN->Encoding->print(S);
|
||||
S += "::";
|
||||
Name = LN->Entity;
|
||||
goto KeepGoingLocalFunction;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionName(char *Buf, size_t *N) const {
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
auto *Name = static_cast<FunctionEncoding *>(RootNode)->getName();
|
||||
return printNode(Name, Buf, N);
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionParameters(char *Buf,
|
||||
size_t *N) const {
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
NodeArray Params = static_cast<FunctionEncoding *>(RootNode)->getParams();
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
|
||||
S += '(';
|
||||
Params.printWithComma(S);
|
||||
S += ')';
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::getFunctionReturnType(
|
||||
char *Buf, size_t *N) const {
|
||||
if (!isFunction())
|
||||
return nullptr;
|
||||
|
||||
OutputStream S;
|
||||
if (!initializeOutputStream(Buf, N, S, 128))
|
||||
return nullptr;
|
||||
|
||||
if (const Node *Ret =
|
||||
static_cast<const FunctionEncoding *>(RootNode)->getReturnType())
|
||||
Ret->print(S);
|
||||
|
||||
S += '\0';
|
||||
if (N != nullptr)
|
||||
*N = S.getCurrentPosition();
|
||||
return S.getBuffer();
|
||||
}
|
||||
|
||||
char *ItaniumPartialDemangler::finishDemangle(char *Buf, size_t *N) const {
|
||||
assert(RootNode != nullptr && "must call partialDemangle()");
|
||||
return printNode(static_cast<Node *>(RootNode), Buf, N);
|
||||
}
|
||||
|
||||
bool ItaniumPartialDemangler::hasFunctionQualifiers() const {
|
||||
assert(RootNode != nullptr && "must call partialDemangle()");
|
||||
if (!isFunction())
|
||||
return false;
|
||||
auto *E = static_cast<const FunctionEncoding *>(RootNode);
|
||||
return E->getCVQuals() != QualNone || E->getRefQual() != FrefQualNone;
|
||||
}
|
||||
|
||||
bool ItaniumPartialDemangler::isCtorOrDtor() const {
|
||||
const Node *N = static_cast<const Node *>(RootNode);
|
||||
while (N) {
|
||||
switch (N->getKind()) {
|
||||
default:
|
||||
return false;
|
||||
case Node::KCtorDtorName:
|
||||
return true;
|
||||
|
||||
case Node::KAbiTagAttr:
|
||||
N = static_cast<const AbiTagAttr *>(N)->Base;
|
||||
break;
|
||||
case Node::KFunctionEncoding:
|
||||
N = static_cast<const FunctionEncoding *>(N)->getName();
|
||||
break;
|
||||
case Node::KLocalName:
|
||||
N = static_cast<const LocalName *>(N)->Entity;
|
||||
break;
|
||||
case Node::KNameWithTemplateArgs:
|
||||
N = static_cast<const NameWithTemplateArgs *>(N)->Name;
|
||||
break;
|
||||
case Node::KNestedName:
|
||||
N = static_cast<const NestedName *>(N)->Name;
|
||||
break;
|
||||
case Node::KStdQualifiedName:
|
||||
N = static_cast<const StdQualifiedName *>(N)->Child;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ItaniumPartialDemangler::isFunction() const {
|
||||
assert(RootNode != nullptr && "must call partialDemangle()");
|
||||
return static_cast<const Node *>(RootNode)->getKind() ==
|
||||
Node::KFunctionEncoding;
|
||||
}
|
||||
|
||||
bool ItaniumPartialDemangler::isSpecialName() const {
|
||||
assert(RootNode != nullptr && "must call partialDemangle()");
|
||||
auto K = static_cast<const Node *>(RootNode)->getKind();
|
||||
return K == Node::KSpecialName || K == Node::KCtorVtableSpecialName;
|
||||
}
|
||||
|
||||
bool ItaniumPartialDemangler::isData() const {
|
||||
return !isFunction() && !isSpecialName();
|
||||
}
|
||||
-104
@@ -1,104 +0,0 @@
|
||||
//===--- Demangle.h ---------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_DEMANGLE_H
|
||||
#define LLVM_DEMANGLE_DEMANGLE_H
|
||||
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
|
||||
namespace llvm {
|
||||
/// This is a llvm local version of __cxa_demangle. Other than the name and
|
||||
/// being in the llvm namespace it is identical.
|
||||
///
|
||||
/// The mangled_name is demangled into buf and returned. If the buffer is not
|
||||
/// large enough, realloc is used to expand it.
|
||||
///
|
||||
/// The *status will be set to a value from the following enumeration
|
||||
enum : int {
|
||||
demangle_unknown_error = -4,
|
||||
demangle_invalid_args = -3,
|
||||
demangle_invalid_mangled_name = -2,
|
||||
demangle_memory_alloc_failure = -1,
|
||||
demangle_success = 0,
|
||||
};
|
||||
|
||||
char *itaniumDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status);
|
||||
|
||||
|
||||
enum MSDemangleFlags {
|
||||
MSDF_None = 0,
|
||||
MSDF_DumpBackrefs = 1 << 0,
|
||||
MSDF_NoAccessSpecifier = 1 << 1,
|
||||
MSDF_NoCallingConvention = 1 << 2,
|
||||
MSDF_NoReturnType = 1 << 3,
|
||||
MSDF_NoMemberType = 1 << 4,
|
||||
};
|
||||
char *microsoftDemangle(const char *mangled_name, char *buf, size_t *n,
|
||||
int *status, MSDemangleFlags Flags = MSDF_None);
|
||||
|
||||
/// "Partial" demangler. This supports demangling a string into an AST
|
||||
/// (typically an intermediate stage in itaniumDemangle) and querying certain
|
||||
/// properties or partially printing the demangled name.
|
||||
struct ItaniumPartialDemangler {
|
||||
ItaniumPartialDemangler();
|
||||
|
||||
ItaniumPartialDemangler(ItaniumPartialDemangler &&Other);
|
||||
ItaniumPartialDemangler &operator=(ItaniumPartialDemangler &&Other);
|
||||
|
||||
/// Demangle into an AST. Subsequent calls to the rest of the member functions
|
||||
/// implicitly operate on the AST this produces.
|
||||
/// \return true on error, false otherwise
|
||||
bool partialDemangle(const char *MangledName);
|
||||
|
||||
/// Just print the entire mangled name into Buf. Buf and N behave like the
|
||||
/// second and third parameters to itaniumDemangle.
|
||||
char *finishDemangle(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the base name of a function. This doesn't include trailing template
|
||||
/// arguments, ie for "a::b<int>" this function returns "b".
|
||||
char *getFunctionBaseName(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the context name for a function. For "a::b::c", this function returns
|
||||
/// "a::b".
|
||||
char *getFunctionDeclContextName(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the entire name of this function.
|
||||
char *getFunctionName(char *Buf, size_t *N) const;
|
||||
|
||||
/// Get the parameters for this function.
|
||||
char *getFunctionParameters(char *Buf, size_t *N) const;
|
||||
char *getFunctionReturnType(char *Buf, size_t *N) const;
|
||||
|
||||
/// If this function has any any cv or reference qualifiers. These imply that
|
||||
/// the function is a non-static member function.
|
||||
bool hasFunctionQualifiers() const;
|
||||
|
||||
/// If this symbol describes a constructor or destructor.
|
||||
bool isCtorOrDtor() const;
|
||||
|
||||
/// If this symbol describes a function.
|
||||
bool isFunction() const;
|
||||
|
||||
/// If this symbol describes a variable.
|
||||
bool isData() const;
|
||||
|
||||
/// If this symbol is a <special-name>. These are generally implicitly
|
||||
/// generated by the implementation, such as vtables and typeinfo names.
|
||||
bool isSpecialName() const;
|
||||
|
||||
~ItaniumPartialDemangler();
|
||||
private:
|
||||
void *RootNode;
|
||||
void *Context;
|
||||
};
|
||||
} // namespace llvm
|
||||
|
||||
#endif
|
||||
@@ -1,93 +0,0 @@
|
||||
//===--- DemangleConfig.h ---------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// This file contains a variety of feature test macros copied from
|
||||
// include/llvm/Support/Compiler.h so that LLVMDemangle does not need to take
|
||||
// a dependency on LLVMSupport.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_DEMANGLE_COMPILER_H
|
||||
#define LLVM_DEMANGLE_COMPILER_H
|
||||
|
||||
#ifndef __has_feature
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_cpp_attribute
|
||||
#define __has_cpp_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef DEMANGLE_GNUC_PREREQ
|
||||
#if defined(__GNUC__) && defined(__GNUC_MINOR__) && defined(__GNUC_PATCHLEVEL__)
|
||||
#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
|
||||
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) + __GNUC_PATCHLEVEL__ >= \
|
||||
((maj) << 20) + ((min) << 10) + (patch))
|
||||
#elif defined(__GNUC__) && defined(__GNUC_MINOR__)
|
||||
#define DEMANGLE_GNUC_PREREQ(maj, min, patch) \
|
||||
((__GNUC__ << 20) + (__GNUC_MINOR__ << 10) >= ((maj) << 20) + ((min) << 10))
|
||||
#else
|
||||
#define DEMANGLE_GNUC_PREREQ(maj, min, patch) 0
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if __has_attribute(used) || DEMANGLE_GNUC_PREREQ(3, 1, 0)
|
||||
#define DEMANGLE_ATTRIBUTE_USED __attribute__((__used__))
|
||||
#else
|
||||
#define DEMANGLE_ATTRIBUTE_USED
|
||||
#endif
|
||||
|
||||
#if __has_builtin(__builtin_unreachable) || DEMANGLE_GNUC_PREREQ(4, 5, 0)
|
||||
#define DEMANGLE_UNREACHABLE __builtin_unreachable()
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEMANGLE_UNREACHABLE __assume(false)
|
||||
#else
|
||||
#define DEMANGLE_UNREACHABLE
|
||||
#endif
|
||||
|
||||
#if __has_attribute(noinline) || DEMANGLE_GNUC_PREREQ(3, 4, 0)
|
||||
#define DEMANGLE_ATTRIBUTE_NOINLINE __attribute__((noinline))
|
||||
#elif defined(_MSC_VER)
|
||||
#define DEMANGLE_ATTRIBUTE_NOINLINE __declspec(noinline)
|
||||
#else
|
||||
#define DEMANGLE_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE DEMANGLE_ATTRIBUTE_USED
|
||||
#else
|
||||
#define DEMANGLE_DUMP_METHOD DEMANGLE_ATTRIBUTE_NOINLINE
|
||||
#endif
|
||||
|
||||
#if __cplusplus > 201402L && __has_cpp_attribute(fallthrough)
|
||||
#define DEMANGLE_FALLTHROUGH [[fallthrough]]
|
||||
#elif __has_cpp_attribute(gnu::fallthrough)
|
||||
#define DEMANGLE_FALLTHROUGH [[gnu::fallthrough]]
|
||||
#elif !__cplusplus
|
||||
// Workaround for llvm.org/PR23435, since clang 3.6 and below emit a spurious
|
||||
// error when __has_cpp_attribute is given a scoped attribute in C mode.
|
||||
#define DEMANGLE_FALLTHROUGH
|
||||
#elif __has_cpp_attribute(clang::fallthrough)
|
||||
#define DEMANGLE_FALLTHROUGH [[clang::fallthrough]]
|
||||
#else
|
||||
#define DEMANGLE_FALLTHROUGH
|
||||
#endif
|
||||
|
||||
#define DEMANGLE_NAMESPACE_BEGIN namespace llvm { namespace itanium_demangle {
|
||||
#define DEMANGLE_NAMESPACE_END } }
|
||||
|
||||
#endif
|
||||
-5582
File diff suppressed because it is too large
Load Diff
-127
@@ -1,127 +0,0 @@
|
||||
//===--- StringView.h -------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// FIXME: Use std::string_view instead when we support C++17.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_STRINGVIEW_H
|
||||
#define DEMANGLE_STRINGVIEW_H
|
||||
|
||||
#include "DemangleConfig.h"
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
class StringView {
|
||||
const char *First;
|
||||
const char *Last;
|
||||
|
||||
public:
|
||||
static const size_t npos = ~size_t(0);
|
||||
|
||||
template <size_t N>
|
||||
StringView(const char (&Str)[N]) : First(Str), Last(Str + N - 1) {}
|
||||
StringView(const char *First_, const char *Last_)
|
||||
: First(First_), Last(Last_) {}
|
||||
StringView(const char *First_, size_t Len)
|
||||
: First(First_), Last(First_ + Len) {}
|
||||
StringView(const char *Str) : First(Str), Last(Str + std::strlen(Str)) {}
|
||||
StringView() : First(nullptr), Last(nullptr) {}
|
||||
|
||||
StringView substr(size_t From) const {
|
||||
return StringView(begin() + From, size() - From);
|
||||
}
|
||||
|
||||
size_t find(char C, size_t From = 0) const {
|
||||
size_t FindBegin = std::min(From, size());
|
||||
// Avoid calling memchr with nullptr.
|
||||
if (FindBegin < size()) {
|
||||
// Just forward to memchr, which is faster than a hand-rolled loop.
|
||||
if (const void *P = ::memchr(First + FindBegin, C, size() - FindBegin))
|
||||
return size_t(static_cast<const char *>(P) - First);
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
|
||||
StringView substr(size_t From, size_t To) const {
|
||||
if (To >= size())
|
||||
To = size() - 1;
|
||||
if (From >= size())
|
||||
From = size() - 1;
|
||||
return StringView(First + From, First + To);
|
||||
}
|
||||
|
||||
StringView dropFront(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
return StringView(First + N, Last);
|
||||
}
|
||||
|
||||
StringView dropBack(size_t N = 1) const {
|
||||
if (N >= size())
|
||||
N = size();
|
||||
return StringView(First, Last - N);
|
||||
}
|
||||
|
||||
char front() const {
|
||||
assert(!empty());
|
||||
return *begin();
|
||||
}
|
||||
|
||||
char back() const {
|
||||
assert(!empty());
|
||||
return *(end() - 1);
|
||||
}
|
||||
|
||||
char popFront() {
|
||||
assert(!empty());
|
||||
return *First++;
|
||||
}
|
||||
|
||||
bool consumeFront(char C) {
|
||||
if (!startsWith(C))
|
||||
return false;
|
||||
*this = dropFront(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool consumeFront(StringView S) {
|
||||
if (!startsWith(S))
|
||||
return false;
|
||||
*this = dropFront(S.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool startsWith(char C) const { return !empty() && *begin() == C; }
|
||||
|
||||
bool startsWith(StringView Str) const {
|
||||
if (Str.size() > size())
|
||||
return false;
|
||||
return std::equal(Str.begin(), Str.end(), begin());
|
||||
}
|
||||
|
||||
const char &operator[](size_t Idx) const { return *(begin() + Idx); }
|
||||
|
||||
const char *begin() const { return First; }
|
||||
const char *end() const { return Last; }
|
||||
size_t size() const { return static_cast<size_t>(Last - First); }
|
||||
bool empty() const { return First == Last; }
|
||||
};
|
||||
|
||||
inline bool operator==(const StringView &LHS, const StringView &RHS) {
|
||||
return LHS.size() == RHS.size() &&
|
||||
std::equal(LHS.begin(), LHS.end(), RHS.begin());
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
-192
@@ -1,192 +0,0 @@
|
||||
//===--- Utility.h ----------------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-FileCopyrightText: Part of the LLVM Project
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
//
|
||||
// Provide some utility classes for use in the demangler(s).
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef DEMANGLE_UTILITY_H
|
||||
#define DEMANGLE_UTILITY_H
|
||||
|
||||
#include "StringView.h"
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
|
||||
DEMANGLE_NAMESPACE_BEGIN
|
||||
|
||||
// Stream that AST nodes write their string representation into after the AST
|
||||
// has been parsed.
|
||||
class OutputStream {
|
||||
char *Buffer;
|
||||
size_t CurrentPosition;
|
||||
size_t BufferCapacity;
|
||||
|
||||
// Ensure there is at least n more positions in buffer.
|
||||
void grow(size_t N) {
|
||||
if (N + CurrentPosition >= BufferCapacity) {
|
||||
BufferCapacity *= 2;
|
||||
if (BufferCapacity < N + CurrentPosition)
|
||||
BufferCapacity = N + CurrentPosition;
|
||||
Buffer = static_cast<char *>(std::realloc(Buffer, BufferCapacity));
|
||||
if (Buffer == nullptr)
|
||||
std::terminate();
|
||||
}
|
||||
}
|
||||
|
||||
void writeUnsigned(uint64_t N, bool isNeg = false) {
|
||||
// Handle special case...
|
||||
if (N == 0) {
|
||||
*this << '0';
|
||||
return;
|
||||
}
|
||||
|
||||
char Temp[21];
|
||||
char *TempPtr = std::end(Temp);
|
||||
|
||||
while (N) {
|
||||
*--TempPtr = '0' + char(N % 10);
|
||||
N /= 10;
|
||||
}
|
||||
|
||||
// Add negative sign...
|
||||
if (isNeg)
|
||||
*--TempPtr = '-';
|
||||
this->operator<<(StringView(TempPtr, std::end(Temp)));
|
||||
}
|
||||
|
||||
public:
|
||||
OutputStream(char *StartBuf, size_t Size)
|
||||
: Buffer(StartBuf), CurrentPosition(0), BufferCapacity(Size) {}
|
||||
OutputStream() = default;
|
||||
void reset(char *Buffer_, size_t BufferCapacity_) {
|
||||
CurrentPosition = 0;
|
||||
Buffer = Buffer_;
|
||||
BufferCapacity = BufferCapacity_;
|
||||
}
|
||||
|
||||
/// If a ParameterPackExpansion (or similar type) is encountered, the offset
|
||||
/// into the pack that we're currently printing.
|
||||
unsigned CurrentPackIndex = std::numeric_limits<unsigned>::max();
|
||||
unsigned CurrentPackMax = std::numeric_limits<unsigned>::max();
|
||||
|
||||
OutputStream &operator+=(StringView R) {
|
||||
size_t Size = R.size();
|
||||
if (Size == 0)
|
||||
return *this;
|
||||
grow(Size);
|
||||
std::memmove(Buffer + CurrentPosition, R.begin(), Size);
|
||||
CurrentPosition += Size;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator+=(char C) {
|
||||
grow(1);
|
||||
Buffer[CurrentPosition++] = C;
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(StringView R) { return (*this += R); }
|
||||
|
||||
OutputStream &operator<<(char C) { return (*this += C); }
|
||||
|
||||
OutputStream &operator<<(long long N) {
|
||||
if (N < 0)
|
||||
writeUnsigned(static_cast<unsigned long long>(-N), true);
|
||||
else
|
||||
writeUnsigned(static_cast<unsigned long long>(N));
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long long N) {
|
||||
writeUnsigned(N, false);
|
||||
return *this;
|
||||
}
|
||||
|
||||
OutputStream &operator<<(long N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned long N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(int N) {
|
||||
return this->operator<<(static_cast<long long>(N));
|
||||
}
|
||||
|
||||
OutputStream &operator<<(unsigned int N) {
|
||||
return this->operator<<(static_cast<unsigned long long>(N));
|
||||
}
|
||||
|
||||
size_t getCurrentPosition() const { return CurrentPosition; }
|
||||
void setCurrentPosition(size_t NewPos) { CurrentPosition = NewPos; }
|
||||
|
||||
char back() const {
|
||||
return CurrentPosition ? Buffer[CurrentPosition - 1] : '\0';
|
||||
}
|
||||
|
||||
bool empty() const { return CurrentPosition == 0; }
|
||||
|
||||
char *getBuffer() { return Buffer; }
|
||||
char *getBufferEnd() { return Buffer + CurrentPosition - 1; }
|
||||
size_t getBufferCapacity() { return BufferCapacity; }
|
||||
};
|
||||
|
||||
template <class T> class SwapAndRestore {
|
||||
T &Restore;
|
||||
T OriginalValue;
|
||||
bool ShouldRestore = true;
|
||||
|
||||
public:
|
||||
SwapAndRestore(T &Restore_) : SwapAndRestore(Restore_, Restore_) {}
|
||||
|
||||
SwapAndRestore(T &Restore_, T NewVal)
|
||||
: Restore(Restore_), OriginalValue(Restore) {
|
||||
Restore = std::move(NewVal);
|
||||
}
|
||||
~SwapAndRestore() {
|
||||
if (ShouldRestore)
|
||||
Restore = std::move(OriginalValue);
|
||||
}
|
||||
|
||||
void shouldRestore(bool ShouldRestore_) { ShouldRestore = ShouldRestore_; }
|
||||
|
||||
void restoreNow(bool Force) {
|
||||
if (!Force && !ShouldRestore)
|
||||
return;
|
||||
|
||||
Restore = std::move(OriginalValue);
|
||||
ShouldRestore = false;
|
||||
}
|
||||
|
||||
SwapAndRestore(const SwapAndRestore &) = delete;
|
||||
SwapAndRestore &operator=(const SwapAndRestore &) = delete;
|
||||
};
|
||||
|
||||
inline bool initializeOutputStream(char *Buf, size_t *N, OutputStream &S,
|
||||
size_t InitSize) {
|
||||
size_t BufferSize;
|
||||
if (Buf == nullptr) {
|
||||
Buf = static_cast<char *>(std::malloc(InitSize));
|
||||
if (Buf == nullptr)
|
||||
return false;
|
||||
BufferSize = InitSize;
|
||||
} else
|
||||
BufferSize = *N;
|
||||
|
||||
S.reset(Buf, BufferSize);
|
||||
return true;
|
||||
}
|
||||
|
||||
DEMANGLE_NAMESPACE_END
|
||||
|
||||
#endif
|
||||
Vendored
+1
-1
Submodule externals/dynarmic updated: 165621a872...bd570e093c
@@ -2,7 +2,9 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(OPUS QUIET IMPORTED_TARGET opus)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Opus
|
||||
@@ -3,7 +3,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(ENET QUIET IMPORTED_TARGET libenet)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(enet
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
# 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)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(HTTPLIB QUIET IMPORTED_TARGET cpp-httplib)
|
||||
endif()
|
||||
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()
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
# SPDX-FileCopyrightText: 2022 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(INIREADER QUIET IMPORTED_TARGET INIReader)
|
||||
endif()
|
||||
|
||||
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()
|
||||
@@ -3,7 +3,9 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(LIBUSB QUIET IMPORTED_TARGET libusb-1.0)
|
||||
endif()
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(libusb
|
||||
@@ -4,11 +4,13 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package(lz4 QUIET CONFIG)
|
||||
if (lz4_CONSIDERED_CONFIGS)
|
||||
if (lz4_FOUND)
|
||||
find_package_handle_standard_args(lz4 CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(LZ4 QUIET IMPORTED_TARGET liblz4)
|
||||
endif()
|
||||
find_package_handle_standard_args(lz4
|
||||
REQUIRED_VARS LZ4_LINK_LIBRARIES
|
||||
VERSION_VAR LZ4_VERSION
|
||||
@@ -4,11 +4,13 @@
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
find_package(zstd QUIET CONFIG)
|
||||
if (zstd_CONSIDERED_CONFIGS)
|
||||
if (zstd_FOUND)
|
||||
find_package_handle_standard_args(zstd CONFIG_MODE)
|
||||
else()
|
||||
find_package(PkgConfig QUIET)
|
||||
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
|
||||
if (PKG_CONFIG_FOUND)
|
||||
pkg_search_module(ZSTD QUIET IMPORTED_TARGET libzstd)
|
||||
endif()
|
||||
find_package_handle_standard_args(zstd
|
||||
REQUIRED_VARS ZSTD_LINK_LIBRARIES
|
||||
VERSION_VAR ZSTD_VERSION
|
||||
+1
Submodule externals/libressl added at 8929f818fd
Vendored
+1
-1
Submodule externals/sirit updated: ab75463999...d7ad93a888
Vendored
+1
-1
Submodule externals/xbyak updated: a1ac3750f9...348e3e548e
+1
-4
@@ -161,10 +161,7 @@ add_subdirectory(video_core)
|
||||
add_subdirectory(network)
|
||||
add_subdirectory(input_common)
|
||||
add_subdirectory(shader_recompiler)
|
||||
|
||||
if (YUZU_ROOM)
|
||||
add_subdirectory(dedicated_room)
|
||||
endif()
|
||||
add_subdirectory(dedicated_room)
|
||||
|
||||
if (YUZU_TESTS)
|
||||
add_subdirectory(tests)
|
||||
|
||||
@@ -187,7 +187,11 @@ add_library(audio_core STATIC
|
||||
renderer/voice/voice_info.cpp
|
||||
renderer/voice/voice_info.h
|
||||
renderer/voice/voice_state.h
|
||||
sink/cubeb_sink.cpp
|
||||
sink/cubeb_sink.h
|
||||
sink/null_sink.h
|
||||
sink/sdl2_sink.cpp
|
||||
sink/sdl2_sink.h
|
||||
sink/sink.h
|
||||
sink/sink_details.cpp
|
||||
sink/sink_details.h
|
||||
@@ -218,22 +222,11 @@ if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64)
|
||||
target_link_libraries(audio_core PRIVATE dynarmic::dynarmic)
|
||||
endif()
|
||||
|
||||
if (ENABLE_CUBEB)
|
||||
target_sources(audio_core PRIVATE
|
||||
sink/cubeb_sink.cpp
|
||||
sink/cubeb_sink.h
|
||||
)
|
||||
|
||||
if(ENABLE_CUBEB)
|
||||
target_link_libraries(audio_core PRIVATE cubeb::cubeb)
|
||||
target_compile_definitions(audio_core PRIVATE -DHAVE_CUBEB=1)
|
||||
endif()
|
||||
|
||||
if (ENABLE_SDL2)
|
||||
target_sources(audio_core PRIVATE
|
||||
sink/sdl2_sink.cpp
|
||||
sink/sdl2_sink.h
|
||||
)
|
||||
|
||||
if(ENABLE_SDL2)
|
||||
target_link_libraries(audio_core PRIVATE SDL2::SDL2)
|
||||
target_compile_definitions(audio_core PRIVATE HAVE_SDL2)
|
||||
endif()
|
||||
|
||||
@@ -91,10 +91,9 @@ public:
|
||||
* @param core_timing - The CoreTiming instance
|
||||
* @param session - The device session
|
||||
*
|
||||
* @return If any buffer was released.
|
||||
* @return Is the buffer was released.
|
||||
*/
|
||||
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session,
|
||||
bool force) {
|
||||
bool ReleaseBuffers(const Core::Timing::CoreTiming& core_timing, const DeviceSession& session) {
|
||||
std::scoped_lock l{lock};
|
||||
bool buffer_released{false};
|
||||
while (registered_count > 0) {
|
||||
@@ -104,8 +103,7 @@ public:
|
||||
}
|
||||
|
||||
// Check with the backend if this buffer can be released yet.
|
||||
// If we're shutting down, we don't care if it's been played or not.
|
||||
if (!force && !session.IsBufferConsumed(buffers[index])) {
|
||||
if (!session.IsBufferConsumed(buffers[index])) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,12 +73,6 @@ 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,11 +90,6 @@ public:
|
||||
*/
|
||||
void Stop();
|
||||
|
||||
/**
|
||||
* Clear out the underlying audio buffers in the backend stream.
|
||||
*/
|
||||
void ClearBuffers();
|
||||
|
||||
/**
|
||||
* Set this device session's volume.
|
||||
*
|
||||
|
||||
@@ -23,6 +23,7 @@ System::~System() {
|
||||
void System::Finalize() {
|
||||
Stop();
|
||||
session->Finalize();
|
||||
buffer_event->Signal();
|
||||
}
|
||||
|
||||
void System::StartSession() {
|
||||
@@ -101,10 +102,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -141,7 +138,7 @@ void System::RegisterBuffers() {
|
||||
}
|
||||
|
||||
void System::ReleaseBuffers() {
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
|
||||
|
||||
if (signal) {
|
||||
// Signal if any buffer was released, or if none are registered, we need more.
|
||||
|
||||
@@ -24,6 +24,7 @@ System::~System() {
|
||||
void System::Finalize() {
|
||||
Stop();
|
||||
session->Finalize();
|
||||
buffer_event->Signal();
|
||||
}
|
||||
|
||||
std::string_view System::GetDefaultOutputDeviceName() const {
|
||||
@@ -101,10 +102,6 @@ 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;
|
||||
}
|
||||
|
||||
@@ -141,7 +138,7 @@ void System::RegisterBuffers() {
|
||||
}
|
||||
|
||||
void System::ReleaseBuffers() {
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session, false)};
|
||||
bool signal{buffers.ReleaseBuffers(system.CoreTiming(), *session)};
|
||||
if (signal) {
|
||||
// Signal if any buffer was released, or if none are registered, we need more.
|
||||
buffer_event->Signal();
|
||||
|
||||
@@ -132,7 +132,7 @@ void AudioRenderer::CreateSinkStreams() {
|
||||
}
|
||||
|
||||
void AudioRenderer::ThreadFunc() {
|
||||
static constexpr char name[]{"AudioRenderer"};
|
||||
constexpr char name[]{"AudioRenderer"};
|
||||
MicroProfileOnThreadCreate(name);
|
||||
Common::SetCurrentThreadName(name);
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::Critical);
|
||||
|
||||
@@ -251,8 +251,8 @@ void CommandBuffer::GenerateBiquadFilterCommand(const s32 node_id, EffectInfoBas
|
||||
|
||||
const auto& parameter{
|
||||
*reinterpret_cast<BiquadFilterInfo::ParameterVersion1*>(effect_info.GetParameter())};
|
||||
const auto state{reinterpret_cast<VoiceState::BiquadFilterState*>(
|
||||
effect_info.GetStateBuffer() + channel * sizeof(VoiceState::BiquadFilterState))};
|
||||
const auto state{
|
||||
reinterpret_cast<VoiceState::BiquadFilterState*>(effect_info.GetStateBuffer())};
|
||||
|
||||
cmd.input = buffer_offset + parameter.inputs[channel];
|
||||
cmd.output = buffer_offset + parameter.outputs[channel];
|
||||
|
||||
@@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
|
||||
while (destination != nullptr) {
|
||||
if (destination->IsConfigured()) {
|
||||
auto mix_id{destination->GetMixId()};
|
||||
if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) {
|
||||
if (mix_id < mix_context.GetCount()) {
|
||||
auto mix_info{mix_context.GetInfo(mix_id)};
|
||||
command_buffer.GenerateDepopPrepareCommand(
|
||||
voice_info.node_id, voice_state, render_context.depop_buffer,
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "audio_core/renderer/adsp/command_list_processor.h"
|
||||
#include "audio_core/renderer/command/effect/aux_.h"
|
||||
#include "audio_core/renderer/effect/aux_.h"
|
||||
#include "core/core.h"
|
||||
#include "core/memory.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
@@ -20,24 +19,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
|
||||
return;
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp info{};
|
||||
auto info_ptr{&info};
|
||||
bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))};
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
info_ptr->read_offset = 0;
|
||||
info_ptr->write_offset = 0;
|
||||
info_ptr->total_sample_count = 0;
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))};
|
||||
info->read_offset = 0;
|
||||
info->write_offset = 0;
|
||||
info->total_sample_count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,10 +40,11 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
|
||||
* @param update_count - If non-zero, send_info_ will be updated.
|
||||
* @return Number of samples written.
|
||||
*/
|
||||
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
[[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max,
|
||||
std::span<const s32> input, u32 write_count_, u32 write_offset,
|
||||
u32 update_count) {
|
||||
static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_,
|
||||
[[maybe_unused]] u32 sample_count, const CpuAddr send_buffer,
|
||||
const u32 count_max, std::span<const s32> input,
|
||||
const u32 write_count_, const u32 write_offset,
|
||||
const u32 update_count) {
|
||||
if (write_count_ > count_max) {
|
||||
LOG_ERROR(Service_Audio,
|
||||
"write_count must be smaller than count_max! write_count {}, count_max {}",
|
||||
@@ -66,11 +52,6 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (send_info_ == 0) {
|
||||
LOG_ERROR(Service_Audio, "send_info_ is 0!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (input.empty()) {
|
||||
LOG_ERROR(Service_Audio, "input buffer is empty!");
|
||||
return 0;
|
||||
@@ -86,47 +67,33 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp send_info{};
|
||||
auto send_ptr = &send_info;
|
||||
bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
|
||||
memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
u32 target_write_offset{send_ptr->write_offset + write_offset};
|
||||
if (target_write_offset > count_max) {
|
||||
u32 target_write_offset{send_info.write_offset + write_offset};
|
||||
if (target_write_offset > count_max || write_count_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 write_count{write_count_};
|
||||
u32 read_pos{0};
|
||||
u32 write_pos{0};
|
||||
while (write_count > 0) {
|
||||
u32 to_write{std::min(count_max - target_write_offset, write_count)};
|
||||
const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
|
||||
bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))};
|
||||
if (write_safe) [[likely]] {
|
||||
auto ptr = memory.GetPointer(write_addr);
|
||||
std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32));
|
||||
} else {
|
||||
|
||||
if (to_write > 0) {
|
||||
memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
|
||||
&input[read_pos], to_write * sizeof(s32));
|
||||
&input[write_pos], to_write * sizeof(s32));
|
||||
}
|
||||
|
||||
target_write_offset = (target_write_offset + to_write) % count_max;
|
||||
write_count -= to_write;
|
||||
read_pos += to_write;
|
||||
write_pos += to_write;
|
||||
}
|
||||
|
||||
if (update_count) {
|
||||
send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max;
|
||||
send_info.write_offset = (send_info.write_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
return write_count_;
|
||||
}
|
||||
@@ -135,7 +102,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
* Read the given memory at return_buffer into the output mix buffer, and update return_info_ if
|
||||
* update_count is set, to notify the game that an update happened.
|
||||
*
|
||||
* @param memory - Core memory for reading.
|
||||
* @param memory - Core memory for writing.
|
||||
* @param return_info_ - Meta information for where to read the mix buffer.
|
||||
* @param return_buffer - Memory address to read the samples from.
|
||||
* @param count_max - Maximum number of samples in the receiving buffer.
|
||||
@@ -145,21 +112,16 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
|
||||
* @param update_count - If non-zero, send_info_ will be updated.
|
||||
* @return Number of samples read.
|
||||
*/
|
||||
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
|
||||
CpuAddr return_buffer, u32 count_max, std::span<s32> output,
|
||||
u32 read_count_, u32 read_offset, u32 update_count) {
|
||||
static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_,
|
||||
const CpuAddr return_buffer, const u32 count_max, std::span<s32> output,
|
||||
const u32 count_, const u32 read_offset, const u32 update_count) {
|
||||
if (count_max == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (read_count_ > count_max) {
|
||||
if (count_ > count_max) {
|
||||
LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}",
|
||||
read_count_, count_max);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (return_info_ == 0) {
|
||||
LOG_ERROR(Service_Audio, "return_info_ is 0!");
|
||||
count_, count_max);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -174,49 +136,35 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
|
||||
}
|
||||
|
||||
AuxInfo::AuxInfoDsp return_info{};
|
||||
auto return_ptr = &return_info;
|
||||
bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
|
||||
memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
if (host_safe) [[likely]] {
|
||||
return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_);
|
||||
} else {
|
||||
memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
|
||||
u32 target_read_offset{return_ptr->read_offset + read_offset};
|
||||
u32 target_read_offset{return_info.read_offset + read_offset};
|
||||
if (target_read_offset > count_max) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 read_count{read_count_};
|
||||
u32 write_pos{0};
|
||||
u32 read_count{count_};
|
||||
u32 read_pos{0};
|
||||
while (read_count > 0) {
|
||||
u32 to_read{std::min(count_max - target_read_offset, read_count)};
|
||||
const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
|
||||
bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <=
|
||||
(Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))};
|
||||
if (read_safe) [[likely]] {
|
||||
auto ptr = memory.GetPointer(read_addr);
|
||||
std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32));
|
||||
} else {
|
||||
|
||||
if (to_read > 0) {
|
||||
memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
|
||||
&output[write_pos], to_read * sizeof(s32));
|
||||
&output[read_pos], to_read * sizeof(s32));
|
||||
}
|
||||
|
||||
target_read_offset = (target_read_offset + to_read) % count_max;
|
||||
read_count -= to_read;
|
||||
write_pos += to_read;
|
||||
read_pos += to_read;
|
||||
}
|
||||
|
||||
if (update_count) {
|
||||
return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max;
|
||||
return_info.read_offset = (return_info.read_offset + update_count) % count_max;
|
||||
}
|
||||
|
||||
if (!host_safe) [[unlikely]] {
|
||||
memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
|
||||
}
|
||||
memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
|
||||
|
||||
return read_count_;
|
||||
return count_;
|
||||
}
|
||||
|
||||
void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
|
||||
@@ -241,7 +189,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
|
||||
update_count)};
|
||||
|
||||
if (read != processor.sample_count) {
|
||||
std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32));
|
||||
std::memset(&output_buffer[read], 0, processor.sample_count - read);
|
||||
}
|
||||
} else {
|
||||
ResetAuxBufferDsp(*processor.memory, send_buffer_info);
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
#include "audio_core/renderer/adsp/command_list_processor.h"
|
||||
#include "audio_core/renderer/command/effect/biquad_filter.h"
|
||||
#include "audio_core/renderer/voice/voice_state.h"
|
||||
#include "common/bit_cast.h"
|
||||
|
||||
namespace AudioCore::AudioRenderer {
|
||||
/**
|
||||
@@ -20,21 +19,21 @@ namespace AudioCore::AudioRenderer {
|
||||
void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
|
||||
std::array<s16, 3>& b_, std::array<s16, 2>& a_,
|
||||
VoiceState::BiquadFilterState& state, const u32 sample_count) {
|
||||
constexpr f64 min{std::numeric_limits<s32>::min()};
|
||||
constexpr f64 max{std::numeric_limits<s32>::max()};
|
||||
constexpr s64 min{std::numeric_limits<s32>::min()};
|
||||
constexpr s64 max{std::numeric_limits<s32>::max()};
|
||||
std::array<f64, 3> b{Common::FixedPoint<50, 14>::from_base(b_[0]).to_double(),
|
||||
Common::FixedPoint<50, 14>::from_base(b_[1]).to_double(),
|
||||
Common::FixedPoint<50, 14>::from_base(b_[2]).to_double()};
|
||||
std::array<f64, 2> a{Common::FixedPoint<50, 14>::from_base(a_[0]).to_double(),
|
||||
Common::FixedPoint<50, 14>::from_base(a_[1]).to_double()};
|
||||
std::array<f64, 4> s{Common::BitCast<f64>(state.s0), Common::BitCast<f64>(state.s1),
|
||||
Common::BitCast<f64>(state.s2), Common::BitCast<f64>(state.s3)};
|
||||
std::array<f64, 4> s{state.s0.to_double(), state.s1.to_double(), state.s2.to_double(),
|
||||
state.s3.to_double()};
|
||||
|
||||
for (u32 i = 0; i < sample_count; i++) {
|
||||
f64 in_sample{static_cast<f64>(input[i])};
|
||||
auto sample{in_sample * b[0] + s[0] * b[1] + s[1] * b[2] + s[2] * a[0] + s[3] * a[1]};
|
||||
|
||||
output[i] = static_cast<s32>(std::clamp(sample, min, max));
|
||||
output[i] = static_cast<s32>(std::clamp(static_cast<s64>(sample), min, max));
|
||||
|
||||
s[1] = s[0];
|
||||
s[0] = in_sample;
|
||||
@@ -42,10 +41,10 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
|
||||
s[2] = sample;
|
||||
}
|
||||
|
||||
state.s0 = Common::BitCast<s64>(s[0]);
|
||||
state.s1 = Common::BitCast<s64>(s[1]);
|
||||
state.s2 = Common::BitCast<s64>(s[2]);
|
||||
state.s3 = Common::BitCast<s64>(s[3]);
|
||||
state.s0 = s[0];
|
||||
state.s1 = s[1];
|
||||
state.s2 = s[2];
|
||||
state.s3 = s[3];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -59,20 +58,29 @@ void ApplyBiquadFilterFloat(std::span<s32> output, std::span<const s32> input,
|
||||
* @param sample_count - Number of samples to process.
|
||||
*/
|
||||
static void ApplyBiquadFilterInt(std::span<s32> output, std::span<const s32> input,
|
||||
std::array<s16, 3>& b, std::array<s16, 2>& a,
|
||||
std::array<s16, 3>& b_, std::array<s16, 2>& a_,
|
||||
VoiceState::BiquadFilterState& state, const u32 sample_count) {
|
||||
constexpr s64 min{std::numeric_limits<s32>::min()};
|
||||
constexpr s64 max{std::numeric_limits<s32>::max()};
|
||||
std::array<Common::FixedPoint<50, 14>, 3> b{
|
||||
Common::FixedPoint<50, 14>::from_base(b_[0]),
|
||||
Common::FixedPoint<50, 14>::from_base(b_[1]),
|
||||
Common::FixedPoint<50, 14>::from_base(b_[2]),
|
||||
};
|
||||
std::array<Common::FixedPoint<50, 14>, 3> a{
|
||||
Common::FixedPoint<50, 14>::from_base(a_[0]),
|
||||
Common::FixedPoint<50, 14>::from_base(a_[1]),
|
||||
};
|
||||
|
||||
for (u32 i = 0; i < sample_count; i++) {
|
||||
const s64 in_sample{input[i]};
|
||||
const s64 sample{in_sample * b[0] + state.s0};
|
||||
const s64 out_sample{std::clamp<s64>((sample + (1 << 13)) >> 14, min, max)};
|
||||
s64 in_sample{input[i]};
|
||||
auto sample{in_sample * b[0] + state.s0};
|
||||
const auto out_sample{std::clamp(sample.to_long(), min, max)};
|
||||
|
||||
output[i] = static_cast<s32>(out_sample);
|
||||
|
||||
state.s0 = state.s1 + b[1] * in_sample + a[0] * out_sample;
|
||||
state.s1 = b[2] * in_sample + a[1] * out_sample;
|
||||
state.s1 = 0 + b[2] * in_sample + a[1] * out_sample;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -244,16 +244,16 @@ template <size_t NumChannels>
|
||||
static void ApplyI3dl2ReverbEffect(I3dl2ReverbInfo::State& state,
|
||||
std::span<std::span<const s32>> inputs,
|
||||
std::span<std::span<s32>> outputs, const u32 sample_count) {
|
||||
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
|
||||
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
|
||||
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
|
||||
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1,
|
||||
};
|
||||
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
|
||||
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
|
||||
0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 3, 3, 3,
|
||||
};
|
||||
static constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
|
||||
constexpr std::array<u8, I3dl2ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
|
||||
2, 0, 0, 1, 1, 1, 1, 4, 4, 4, 1, 1, 1, 0, 0, 0, 0, 5, 5, 5,
|
||||
};
|
||||
|
||||
|
||||
@@ -252,16 +252,16 @@ template <size_t NumChannels>
|
||||
static void ApplyReverbEffect(const ReverbInfo::ParameterVersion2& params, ReverbInfo::State& state,
|
||||
std::vector<std::span<const s32>>& inputs,
|
||||
std::vector<std::span<s32>>& outputs, const u32 sample_count) {
|
||||
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
|
||||
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes1Ch{
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
|
||||
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes2Ch{
|
||||
0, 0, 1, 1, 0, 1, 0, 0, 1, 1,
|
||||
};
|
||||
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
|
||||
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes4Ch{
|
||||
0, 0, 1, 1, 0, 1, 2, 2, 3, 3,
|
||||
};
|
||||
static constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
|
||||
constexpr std::array<u8, ReverbInfo::MaxDelayTaps> OutTapIndexes6Ch{
|
||||
0, 0, 1, 1, 2, 2, 4, 4, 5, 5,
|
||||
};
|
||||
|
||||
|
||||
@@ -19,26 +19,26 @@ namespace AudioCore::AudioRenderer {
|
||||
static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
|
||||
const u32 target_sample_count, const u32 source_sample_count,
|
||||
UpsamplerState* state) {
|
||||
static constexpr u32 WindowSize = 10;
|
||||
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc1{
|
||||
0.95376587f, -0.12872314f, 0.060028076f, -0.032470703f, 0.017669678f,
|
||||
-0.009124756f, 0.004272461f, -0.001739502f, 0.000579834f, -0.000091552734f,
|
||||
constexpr u32 WindowSize = 10;
|
||||
constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow1{
|
||||
51.93359375f, -18.80078125f, 9.73046875f, -5.33203125f, 2.84375f,
|
||||
-1.41015625f, 0.62109375f, -0.2265625f, 0.0625f, -0.00390625f,
|
||||
};
|
||||
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc2{
|
||||
0.8230896f, -0.19161987f, 0.093444824f, -0.05090332f, 0.027557373f,
|
||||
-0.014038086f, 0.0064697266f, -0.002532959f, 0.00079345703f, -0.00012207031f,
|
||||
constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow2{
|
||||
105.35546875f, -24.52734375f, 11.9609375f, -6.515625f, 3.52734375f,
|
||||
-1.796875f, 0.828125f, -0.32421875f, 0.1015625f, -0.015625f,
|
||||
};
|
||||
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc3{
|
||||
0.6298828f, -0.19274902f, 0.09725952f, -0.05319214f, 0.028625488f,
|
||||
-0.014373779f, 0.006500244f, -0.0024719238f, 0.0007324219f, -0.000091552734f,
|
||||
constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow3{
|
||||
122.08203125f, -16.47656250f, 7.68359375f, -4.15625000f, 2.26171875f,
|
||||
-1.16796875f, 0.54687500f, -0.22265625f, 0.07421875f, -0.01171875f,
|
||||
};
|
||||
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc4{
|
||||
0.4057312f, -0.1468811f, 0.07601929f, -0.041656494f, 0.022216797f,
|
||||
-0.011016846f, 0.004852295f, -0.0017700195f, 0.00048828125f, -0.000030517578f,
|
||||
constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow4{
|
||||
23.73437500f, -9.62109375f, 5.07812500f, -2.78125000f, 1.46875000f,
|
||||
-0.71484375f, 0.30859375f, -0.10546875f, 0.02734375f, 0.00000000f,
|
||||
};
|
||||
static constexpr std::array<Common::FixedPoint<17, 15>, WindowSize> WindowedSinc5{
|
||||
0.1854248f, -0.075164795f, 0.03967285f, -0.021728516f, 0.011474609f,
|
||||
-0.005584717f, 0.0024108887f, -0.0008239746f, 0.00021362305f, 0.0f,
|
||||
constexpr std::array<Common::FixedPoint<24, 8>, WindowSize> SincWindow5{
|
||||
80.62500000f, -24.67187500f, 12.44921875f, -6.80859375f, 3.66406250f,
|
||||
-1.83984375f, 0.83203125f, -0.31640625f, 0.09375000f, -0.01171875f,
|
||||
};
|
||||
|
||||
if (!state->initialized) {
|
||||
@@ -91,31 +91,52 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
|
||||
static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize);
|
||||
};
|
||||
|
||||
auto calculate_sample = [&state](std::span<const Common::FixedPoint<17, 15>> coeffs1,
|
||||
std::span<const Common::FixedPoint<17, 15>> coeffs2) -> s32 {
|
||||
auto calculate_sample = [&state](std::span<const Common::FixedPoint<24, 8>> coeffs1,
|
||||
std::span<const Common::FixedPoint<24, 8>> coeffs2) -> s32 {
|
||||
auto output_index{state->history_output_index};
|
||||
u64 result{0};
|
||||
auto start_pos{output_index - state->history_start_index + 1U};
|
||||
auto end_pos{10U};
|
||||
|
||||
for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) {
|
||||
result += static_cast<u64>(state->history[output_index].to_raw()) *
|
||||
coeffs1[coeff_index].to_raw();
|
||||
if (start_pos < 10) {
|
||||
end_pos = start_pos;
|
||||
}
|
||||
|
||||
output_index = output_index == state->history_start_index ? state->history_end_index
|
||||
: output_index - 1;
|
||||
u64 prev_contrib{0};
|
||||
u32 coeff_index{0};
|
||||
for (; coeff_index < end_pos; coeff_index++, output_index--) {
|
||||
prev_contrib += static_cast<u64>(state->history[output_index].to_raw()) *
|
||||
coeffs1[coeff_index].to_raw();
|
||||
}
|
||||
|
||||
auto end_index{state->history_end_index};
|
||||
for (; start_pos < 9; start_pos++, coeff_index++, end_index--) {
|
||||
prev_contrib += static_cast<u64>(state->history[end_index].to_raw()) *
|
||||
coeffs1[coeff_index].to_raw();
|
||||
}
|
||||
|
||||
output_index =
|
||||
static_cast<u16>((state->history_output_index + 1) % UpsamplerState::HistorySize);
|
||||
start_pos = state->history_end_index - output_index + 1U;
|
||||
end_pos = 10U;
|
||||
|
||||
for (u32 coeff_index = 0; coeff_index < 10; coeff_index++) {
|
||||
result += static_cast<u64>(state->history[output_index].to_raw()) *
|
||||
coeffs2[coeff_index].to_raw();
|
||||
|
||||
output_index = output_index == state->history_end_index ? state->history_start_index
|
||||
: output_index + 1;
|
||||
if (start_pos < 10) {
|
||||
end_pos = start_pos;
|
||||
}
|
||||
|
||||
return static_cast<s32>(result >> (8 + 15));
|
||||
u64 next_contrib{0};
|
||||
coeff_index = 0;
|
||||
for (; coeff_index < end_pos; coeff_index++, output_index++) {
|
||||
next_contrib += static_cast<u64>(state->history[output_index].to_raw()) *
|
||||
coeffs2[coeff_index].to_raw();
|
||||
}
|
||||
|
||||
auto start_index{state->history_start_index};
|
||||
for (; start_pos < 9; start_pos++, start_index++, coeff_index++) {
|
||||
next_contrib += static_cast<u64>(state->history[start_index].to_raw()) *
|
||||
coeffs2[coeff_index].to_raw();
|
||||
}
|
||||
|
||||
return static_cast<s32>(((prev_contrib >> 15) + (next_contrib >> 15)) >> 8);
|
||||
};
|
||||
|
||||
switch (state->ratio.to_int_floor()) {
|
||||
@@ -129,23 +150,23 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
|
||||
break;
|
||||
|
||||
case 1:
|
||||
output[write_index] = calculate_sample(WindowedSinc1, WindowedSinc5);
|
||||
output[write_index] = calculate_sample(SincWindow3, SincWindow4);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4);
|
||||
output[write_index] = calculate_sample(SincWindow2, SincWindow1);
|
||||
break;
|
||||
|
||||
case 3:
|
||||
output[write_index] = calculate_sample(WindowedSinc3, WindowedSinc3);
|
||||
output[write_index] = calculate_sample(SincWindow5, SincWindow5);
|
||||
break;
|
||||
|
||||
case 4:
|
||||
output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2);
|
||||
output[write_index] = calculate_sample(SincWindow1, SincWindow2);
|
||||
break;
|
||||
|
||||
case 5:
|
||||
output[write_index] = calculate_sample(WindowedSinc5, WindowedSinc1);
|
||||
output[write_index] = calculate_sample(SincWindow4, SincWindow3);
|
||||
break;
|
||||
}
|
||||
state->sample_index = static_cast<u8>((state->sample_index + 1) % 6);
|
||||
@@ -162,11 +183,11 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
|
||||
break;
|
||||
|
||||
case 1:
|
||||
output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4);
|
||||
output[write_index] = calculate_sample(SincWindow2, SincWindow1);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2);
|
||||
output[write_index] = calculate_sample(SincWindow1, SincWindow2);
|
||||
break;
|
||||
}
|
||||
state->sample_index = static_cast<u8>((state->sample_index + 1) % 3);
|
||||
@@ -183,12 +204,12 @@ static void SrcProcessFrame(std::span<s32> output, std::span<const s32> input,
|
||||
break;
|
||||
|
||||
case 1:
|
||||
output[write_index] = calculate_sample(WindowedSinc4, WindowedSinc2);
|
||||
output[write_index] = calculate_sample(SincWindow1, SincWindow2);
|
||||
break;
|
||||
|
||||
case 2:
|
||||
increment();
|
||||
output[write_index] = calculate_sample(WindowedSinc2, WindowedSinc4);
|
||||
output[write_index] = calculate_sample(SincWindow2, SincWindow1);
|
||||
break;
|
||||
}
|
||||
state->sample_index = static_cast<u8>((state->sample_index + 1) % 3);
|
||||
|
||||
@@ -127,7 +127,7 @@ Result System::Initialize(const AudioRendererParameterInternal& params,
|
||||
render_device = params.rendering_device;
|
||||
execution_mode = params.execution_mode;
|
||||
|
||||
core.Memory().ZeroBlock(*core.ApplicationProcess(), transfer_memory->GetSourceAddress(),
|
||||
core.Memory().ZeroBlock(*core.Kernel().CurrentProcess(), transfer_memory->GetSourceAddress(),
|
||||
transfer_memory_size);
|
||||
|
||||
// Note: We're not actually using the transfer memory because it's a pain to code for.
|
||||
|
||||
@@ -94,7 +94,7 @@ bool SystemManager::Remove(System& system_) {
|
||||
}
|
||||
|
||||
void SystemManager::ThreadFunc() {
|
||||
static constexpr char name[]{"AudioRenderSystemManager"};
|
||||
constexpr char name[]{"AudioRenderSystemManager"};
|
||||
MicroProfileOnThreadCreate(name);
|
||||
Common::SetCurrentThreadName(name);
|
||||
Common::SetCurrentThreadPriority(Common::ThreadPriority::High);
|
||||
|
||||
@@ -19,10 +19,10 @@ struct VoiceState {
|
||||
* State of the voice's biquad filter.
|
||||
*/
|
||||
struct BiquadFilterState {
|
||||
s64 s0;
|
||||
s64 s1;
|
||||
s64 s2;
|
||||
s64 s3;
|
||||
Common::FixedPoint<50, 14> s0;
|
||||
Common::FixedPoint<50, 14> s1;
|
||||
Common::FixedPoint<50, 14> s2;
|
||||
Common::FixedPoint<50, 14> s3;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -302,21 +302,11 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
|
||||
std::vector<std::string> device_list;
|
||||
cubeb* ctx;
|
||||
|
||||
#ifdef _WIN32
|
||||
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
#endif
|
||||
|
||||
if (cubeb_init(&ctx, "yuzu Device Enumerator", nullptr) != CUBEB_OK) {
|
||||
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
|
||||
return {};
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (SUCCEEDED(com_init_result)) {
|
||||
CoUninitialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
auto type{capture ? CUBEB_DEVICE_TYPE_INPUT : CUBEB_DEVICE_TYPE_OUTPUT};
|
||||
cubeb_device_collection collection;
|
||||
if (cubeb_enumerate_devices(ctx, type, &collection) != CUBEB_OK) {
|
||||
@@ -339,22 +329,12 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
|
||||
u32 GetCubebLatency() {
|
||||
cubeb* ctx;
|
||||
|
||||
#ifdef _WIN32
|
||||
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
|
||||
#endif
|
||||
|
||||
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
|
||||
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
|
||||
// Return a large latency so we choose SDL instead.
|
||||
return 10000u;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
if (SUCCEEDED(com_init_result)) {
|
||||
CoUninitialize();
|
||||
}
|
||||
#endif
|
||||
|
||||
cubeb_stream_params params{};
|
||||
params.rate = TargetSampleRate;
|
||||
params.channels = 2;
|
||||
|
||||
@@ -35,7 +35,7 @@ void SinkStream::AppendBuffer(SinkBuffer& buffer, std::vector<s16>& samples) {
|
||||
|
||||
if (system_channels == 6 && device_channels == 2) {
|
||||
// We're given 6 channels, but our device only outputs 2, so downmix.
|
||||
static constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
|
||||
constexpr std::array<f32, 4> down_mix_coeff{1.0f, 0.707f, 0.251f, 0.707f};
|
||||
|
||||
for (u32 read_index = 0, write_index = 0; read_index < samples.size();
|
||||
read_index += system_channels, write_index += device_channels) {
|
||||
@@ -202,7 +202,7 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
|
||||
// If we're paused or going to shut down, we don't want to consume buffers as coretiming is
|
||||
// paused and we'll desync, so just play silence.
|
||||
if (system.IsPaused() || system.IsShuttingDown()) {
|
||||
static constexpr std::array<s16, 6> silence{};
|
||||
constexpr std::array<s16, 6> silence{};
|
||||
for (size_t i = frames_written; i < num_frames; i++) {
|
||||
std::memcpy(&output_buffer[i * frame_size], &silence[0], frame_size_bytes);
|
||||
}
|
||||
@@ -270,7 +270,7 @@ void SinkStream::Stall() {
|
||||
if (stalled_lock) {
|
||||
return;
|
||||
}
|
||||
stalled_lock = system.StallApplication();
|
||||
stalled_lock = system.StallProcesses();
|
||||
}
|
||||
|
||||
void SinkStream::Unstall() {
|
||||
@@ -278,7 +278,7 @@ void SinkStream::Unstall() {
|
||||
if (!stalled_lock) {
|
||||
return;
|
||||
}
|
||||
system.UnstallApplication();
|
||||
system.UnstallProcesses();
|
||||
stalled_lock.unlock();
|
||||
}
|
||||
|
||||
|
||||
@@ -38,8 +38,6 @@ add_library(common STATIC
|
||||
common_precompiled_headers.h
|
||||
common_types.h
|
||||
concepts.h
|
||||
demangle.cpp
|
||||
demangle.h
|
||||
div_ceil.h
|
||||
dynamic_library.cpp
|
||||
dynamic_library.h
|
||||
@@ -80,7 +78,6 @@ add_library(common STATIC
|
||||
logging/types.h
|
||||
lz4_compression.cpp
|
||||
lz4_compression.h
|
||||
make_unique_for_overwrite.h
|
||||
math_util.h
|
||||
memory_detect.cpp
|
||||
memory_detect.h
|
||||
@@ -99,13 +96,11 @@ add_library(common STATIC
|
||||
point.h
|
||||
precompiled_headers.h
|
||||
quaternion.h
|
||||
range_map.h
|
||||
reader_writer_queue.h
|
||||
ring_buffer.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/scm_rev.cpp
|
||||
scm_rev.h
|
||||
scope_exit.h
|
||||
scratch_buffer.h
|
||||
settings.cpp
|
||||
settings.h
|
||||
settings_input.cpp
|
||||
@@ -176,8 +171,8 @@ endif()
|
||||
|
||||
create_target_directory_groups(common)
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::context Boost::headers fmt::fmt microprofile Threads::Threads)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd LLVM::Demangle)
|
||||
target_link_libraries(common PUBLIC ${Boost_LIBRARIES} fmt::fmt microprofile Threads::Threads)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd)
|
||||
|
||||
if (YUZU_USE_PRECOMPILED_HEADERS)
|
||||
target_precompile_headers(common PRIVATE precompiled_headers.h)
|
||||
|
||||
@@ -12,8 +12,7 @@
|
||||
|
||||
namespace Common {
|
||||
template <typename VaType, size_t AddressSpaceBits>
|
||||
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >=
|
||||
AddressSpaceBits;
|
||||
concept AddressSpaceValid = std::is_unsigned_v<VaType> && sizeof(VaType) * 8 >= AddressSpaceBits;
|
||||
|
||||
struct EmptyStruct {};
|
||||
|
||||
@@ -22,7 +21,7 @@ struct EmptyStruct {};
|
||||
*/
|
||||
template <typename VaType, VaType UnmappedVa, typename PaType, PaType UnmappedPa,
|
||||
bool PaContigSplit, size_t AddressSpaceBits, typename ExtraBlockInfo = EmptyStruct>
|
||||
requires AddressSpaceValid<VaType, AddressSpaceBits>
|
||||
requires AddressSpaceValid<VaType, AddressSpaceBits>
|
||||
class FlatAddressSpaceMap {
|
||||
public:
|
||||
/// The maximum VA that this AS can technically reach
|
||||
@@ -110,7 +109,7 @@ private:
|
||||
* initial, fast linear pass and a subsequent slower pass that iterates until it finds a free block
|
||||
*/
|
||||
template <typename VaType, VaType UnmappedVa, size_t AddressSpaceBits>
|
||||
requires AddressSpaceValid<VaType, AddressSpaceBits>
|
||||
requires AddressSpaceValid<VaType, AddressSpaceBits>
|
||||
class FlatAllocator
|
||||
: public FlatAddressSpaceMap<VaType, UnmappedVa, bool, false, false, AddressSpaceBits> {
|
||||
private:
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace Common {
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignUp(T value, size_t size) {
|
||||
auto mod{static_cast<T>(value % size)};
|
||||
value -= mod;
|
||||
@@ -18,31 +18,31 @@ template <typename T>
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignUpLog2(T value, size_t align_log2) {
|
||||
return static_cast<T>((value + ((1ULL << align_log2) - 1)) >> align_log2 << align_log2);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr T AlignDown(T value, size_t size) {
|
||||
return static_cast<T>(value - value % size);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool Is4KBAligned(T value) {
|
||||
return (value & 0xFFF) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool IsWordAligned(T value) {
|
||||
return (value & 0b11) == 0;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_integral_v<T>
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] constexpr bool IsAligned(T value, size_t alignment) {
|
||||
using U = typename std::make_unsigned_t<T>;
|
||||
const U mask = static_cast<U>(alignment - 1);
|
||||
@@ -50,7 +50,7 @@ template <typename T>
|
||||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
requires std::is_integral_v<T>
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] constexpr T DivideUp(T x, U y) {
|
||||
return (x + (y - 1)) / y;
|
||||
}
|
||||
@@ -73,11 +73,11 @@ public:
|
||||
constexpr AlignmentAllocator(const AlignmentAllocator<T2, Align>&) noexcept {}
|
||||
|
||||
[[nodiscard]] T* allocate(size_type n) {
|
||||
return static_cast<T*>(::operator new(n * sizeof(T), std::align_val_t{Align}));
|
||||
return static_cast<T*>(::operator new (n * sizeof(T), std::align_val_t{Align}));
|
||||
}
|
||||
|
||||
void deallocate(T* p, size_type n) {
|
||||
::operator delete(p, n * sizeof(T), std::align_val_t{Align});
|
||||
::operator delete (p, n * sizeof(T), std::align_val_t{Align});
|
||||
}
|
||||
|
||||
template <typename T2>
|
||||
|
||||
+2
-2
@@ -69,7 +69,7 @@ void assert_fail_impl();
|
||||
#define ASSERT_OR_EXECUTE(_a_, _b_) \
|
||||
do { \
|
||||
ASSERT(_a_); \
|
||||
if (!(_a_)) [[unlikely]] { \
|
||||
if (!(_a_)) { \
|
||||
_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_)) [[unlikely]] { \
|
||||
if (!(_a_)) { \
|
||||
_b_ \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@@ -75,7 +75,7 @@ extern "C" void AnnotateHappensAfter(const char*, int, void*);
|
||||
#if defined(AE_VCPP) || defined(AE_ICC)
|
||||
#define AE_FORCEINLINE __forceinline
|
||||
#elif defined(AE_GCC)
|
||||
// #define AE_FORCEINLINE __attribute__((always_inline))
|
||||
//#define AE_FORCEINLINE __attribute__((always_inline))
|
||||
#define AE_FORCEINLINE inline
|
||||
#else
|
||||
#define AE_FORCEINLINE inline
|
||||
|
||||
@@ -45,19 +45,19 @@ template <typename T>
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_unsigned_v<T>
|
||||
requires std::is_unsigned_v<T>
|
||||
[[nodiscard]] constexpr bool IsPow2(T value) {
|
||||
return std::has_single_bit(value);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
requires std::is_integral_v<T>
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] T NextPow2(T value) {
|
||||
return static_cast<T>(1ULL << ((8U * sizeof(T)) - std::countl_zero(value - 1U)));
|
||||
}
|
||||
|
||||
template <size_t bit_index, typename T>
|
||||
requires std::is_integral_v<T>
|
||||
requires std::is_integral_v<T>
|
||||
[[nodiscard]] constexpr bool Bit(const T value) {
|
||||
static_assert(bit_index < BitSize<T>(), "bit_index must be smaller than size of T");
|
||||
return ((value >> bit_index) & T(1)) == T(1);
|
||||
|
||||
@@ -16,9 +16,9 @@ concept IsContiguousContainer = std::contiguous_iterator<typename T::iterator>;
|
||||
// is available on all supported platforms.
|
||||
template <typename Derived, typename Base>
|
||||
concept DerivedFrom = requires {
|
||||
std::is_base_of_v<Base, Derived>;
|
||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||
};
|
||||
std::is_base_of_v<Base, Derived>;
|
||||
std::is_convertible_v<const volatile Derived*, const volatile Base*>;
|
||||
};
|
||||
|
||||
// TODO: Replace with std::convertible_to when libc++ implements it.
|
||||
template <typename From, typename To>
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <llvm/Demangle/Demangle.h>
|
||||
|
||||
#include "common/demangle.h"
|
||||
#include "common/scope_exit.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
std::string DemangleSymbol(const std::string& mangled) {
|
||||
auto is_itanium = [](const std::string& name) -> bool {
|
||||
// A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
|
||||
auto pos = name.find_first_not_of('_');
|
||||
return pos > 0 && pos <= 4 && pos < name.size() && name[pos] == 'Z';
|
||||
};
|
||||
|
||||
if (mangled.empty()) {
|
||||
return mangled;
|
||||
}
|
||||
|
||||
char* demangled = nullptr;
|
||||
SCOPE_EXIT({ std::free(demangled); });
|
||||
|
||||
if (is_itanium(mangled)) {
|
||||
demangled = llvm::itaniumDemangle(mangled.c_str(), nullptr, nullptr, nullptr);
|
||||
}
|
||||
|
||||
if (!demangled) {
|
||||
return mangled;
|
||||
}
|
||||
return demangled;
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
@@ -1,12 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace Common {
|
||||
|
||||
std::string DemangleSymbol(const std::string& mangled);
|
||||
|
||||
} // namespace Common
|
||||
@@ -10,14 +10,14 @@ namespace Common {
|
||||
|
||||
/// Ceiled integer division.
|
||||
template <typename N, typename D>
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
[[nodiscard]] constexpr N DivCeil(N number, D divisor) {
|
||||
return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor);
|
||||
}
|
||||
|
||||
/// Ceiled integer division with logarithmic divisor in base 2
|
||||
template <typename N, typename D>
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
requires std::is_integral_v<N> && std::is_unsigned_v<D>
|
||||
[[nodiscard]] constexpr N DivCeilLog2(N value, D alignment_log2) {
|
||||
return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2);
|
||||
}
|
||||
|
||||
+30
-30
@@ -64,7 +64,7 @@ struct no_init_t {
|
||||
* Additionally, this requires E to be trivially destructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_destructible_v<T>>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
struct expected_storage_base {
|
||||
constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {}
|
||||
|
||||
@@ -111,7 +111,7 @@ struct expected_storage_base {
|
||||
* Additionally, this requires E to be trivially destructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
requires std::is_trivially_destructible_v<E>
|
||||
struct expected_storage_base<T, E, true> {
|
||||
constexpr expected_storage_base() : m_val{T{}}, m_has_val{true} {}
|
||||
|
||||
@@ -251,7 +251,7 @@ struct expected_operations_base : expected_storage_base<T, E> {
|
||||
* Additionally, this requires E to be trivially copy constructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_copy_constructible_v<T>>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
struct expected_copy_base : expected_operations_base<T, E> {
|
||||
using expected_operations_base<T, E>::expected_operations_base;
|
||||
};
|
||||
@@ -261,7 +261,7 @@ struct expected_copy_base : expected_operations_base<T, E> {
|
||||
* Additionally, this requires E to be trivially copy constructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
requires std::is_trivially_copy_constructible_v<E>
|
||||
struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
|
||||
using expected_operations_base<T, E>::expected_operations_base;
|
||||
|
||||
@@ -289,7 +289,7 @@ struct expected_copy_base<T, E, false> : expected_operations_base<T, E> {
|
||||
* Additionally, this requires E to be trivially move constructible
|
||||
*/
|
||||
template <typename T, typename E, bool = std::is_trivially_move_constructible_v<T>>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
struct expected_move_base : expected_copy_base<T, E> {
|
||||
using expected_copy_base<T, E>::expected_copy_base;
|
||||
};
|
||||
@@ -299,7 +299,7 @@ struct expected_move_base : expected_copy_base<T, E> {
|
||||
* Additionally, this requires E to be trivially move constructible
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
requires std::is_trivially_move_constructible_v<E>
|
||||
struct expected_move_base<T, E, false> : expected_copy_base<T, E> {
|
||||
using expected_copy_base<T, E>::expected_copy_base;
|
||||
|
||||
@@ -330,9 +330,9 @@ template <typename T, typename E,
|
||||
bool = std::conjunction_v<std::is_trivially_copy_assignable<T>,
|
||||
std::is_trivially_copy_constructible<T>,
|
||||
std::is_trivially_destructible<T>>>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_copy_assign_base : expected_move_base<T, E> {
|
||||
using expected_move_base<T, E>::expected_move_base;
|
||||
};
|
||||
@@ -342,9 +342,9 @@ struct expected_copy_assign_base : expected_move_base<T, E> {
|
||||
* Additionally, this requires E to be trivially copy assignable
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
requires std::conjunction_v<std::is_trivially_copy_assignable<E>,
|
||||
std::is_trivially_copy_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_copy_assign_base<T, E, false> : expected_move_base<T, E> {
|
||||
using expected_move_base<T, E>::expected_move_base;
|
||||
|
||||
@@ -371,9 +371,9 @@ template <typename T, typename E,
|
||||
bool = std::conjunction_v<std::is_trivially_move_assignable<T>,
|
||||
std::is_trivially_move_constructible<T>,
|
||||
std::is_trivially_destructible<T>>>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||
};
|
||||
@@ -383,9 +383,9 @@ struct expected_move_assign_base : expected_copy_assign_base<T, E> {
|
||||
* Additionally, this requires E to be trivially move assignable
|
||||
*/
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
requires std::conjunction_v<std::is_trivially_move_assignable<E>,
|
||||
std::is_trivially_move_constructible<E>,
|
||||
std::is_trivially_destructible<E>>
|
||||
struct expected_move_assign_base<T, E, false> : expected_copy_assign_base<T, E> {
|
||||
using expected_copy_assign_base<T, E>::expected_copy_assign_base;
|
||||
|
||||
@@ -412,7 +412,7 @@ struct expected_move_assign_base<T, E, false> : expected_copy_assign_base<T, E>
|
||||
*/
|
||||
template <typename T, typename E, bool EnableCopy = std::is_copy_constructible_v<T>,
|
||||
bool EnableMove = std::is_move_constructible_v<T>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = default;
|
||||
@@ -422,7 +422,7 @@ struct expected_delete_ctor_base {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, true, false> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = default;
|
||||
@@ -432,7 +432,7 @@ struct expected_delete_ctor_base<T, E, true, false> {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, false, true> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = delete;
|
||||
@@ -442,7 +442,7 @@ struct expected_delete_ctor_base<T, E, false, true> {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>>
|
||||
struct expected_delete_ctor_base<T, E, false, false> {
|
||||
expected_delete_ctor_base() = default;
|
||||
expected_delete_ctor_base(const expected_delete_ctor_base&) = delete;
|
||||
@@ -460,8 +460,8 @@ template <
|
||||
typename T, typename E,
|
||||
bool EnableCopy = std::conjunction_v<std::is_copy_constructible<T>, std::is_copy_assignable<T>>,
|
||||
bool EnableMove = std::conjunction_v<std::is_move_constructible<T>, std::is_move_assignable<T>>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
@@ -471,8 +471,8 @@ struct expected_delete_assign_base {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, true, false> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
@@ -482,8 +482,8 @@ struct expected_delete_assign_base<T, E, true, false> {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, false, true> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
@@ -493,8 +493,8 @@ struct expected_delete_assign_base<T, E, false, true> {
|
||||
};
|
||||
|
||||
template <typename T, typename E>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
requires std::conjunction_v<std::is_copy_constructible<E>, std::is_move_constructible<E>,
|
||||
std::is_copy_assignable<E>, std::is_move_assignable<E>>
|
||||
struct expected_delete_assign_base<T, E, false, false> {
|
||||
expected_delete_assign_base() = default;
|
||||
expected_delete_assign_base(const expected_delete_assign_base&) = default;
|
||||
|
||||
@@ -393,27 +393,12 @@ public:
|
||||
}
|
||||
|
||||
// Virtual memory initialization
|
||||
#if defined(__FreeBSD__)
|
||||
virtual_base =
|
||||
static_cast<u8*>(mmap(nullptr, virtual_size, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_ALIGNED_SUPER, -1, 0));
|
||||
if (virtual_base == MAP_FAILED) {
|
||||
virtual_base = static_cast<u8*>(
|
||||
mmap(nullptr, virtual_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
if (virtual_base == MAP_FAILED) {
|
||||
LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno));
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
}
|
||||
#else
|
||||
virtual_base = static_cast<u8*>(mmap(nullptr, virtual_size, PROT_NONE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_NORESERVE, -1, 0));
|
||||
virtual_base = static_cast<u8*>(
|
||||
mmap(nullptr, virtual_size, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
if (virtual_base == MAP_FAILED) {
|
||||
LOG_CRITICAL(HW_Memory, "mmap failed: {}", strerror(errno));
|
||||
throw std::bad_alloc{};
|
||||
}
|
||||
madvise(virtual_base, virtual_size, MADV_HUGEPAGE);
|
||||
#endif
|
||||
|
||||
good = true;
|
||||
}
|
||||
|
||||
+30
-43
@@ -51,8 +51,6 @@ enum class PollingMode {
|
||||
NFC,
|
||||
// Enable infrared camera polling
|
||||
IR,
|
||||
// Enable ring controller polling
|
||||
Ring,
|
||||
};
|
||||
|
||||
enum class CameraFormat {
|
||||
@@ -64,22 +62,21 @@ enum class CameraFormat {
|
||||
None,
|
||||
};
|
||||
|
||||
// Different results that can happen from a device request
|
||||
enum class DriverResult {
|
||||
Success,
|
||||
WrongReply,
|
||||
Timeout,
|
||||
UnsupportedControllerType,
|
||||
HandleInUse,
|
||||
ErrorReadingData,
|
||||
ErrorWritingData,
|
||||
NoDeviceDetected,
|
||||
InvalidHandle,
|
||||
// Vibration reply from the controller
|
||||
enum class VibrationError {
|
||||
None,
|
||||
NotSupported,
|
||||
Disabled,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
// Polling mode reply from the controller
|
||||
enum class PollingError {
|
||||
None,
|
||||
NotSupported,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
// Nfc reply from the controller
|
||||
enum class NfcState {
|
||||
Success,
|
||||
@@ -93,6 +90,13 @@ enum class NfcState {
|
||||
Unknown,
|
||||
};
|
||||
|
||||
// Ir camera reply from the controller
|
||||
enum class CameraError {
|
||||
None,
|
||||
NotSupported,
|
||||
Unknown,
|
||||
};
|
||||
|
||||
// Hint for amplification curve to be used
|
||||
enum class VibrationAmplificationType {
|
||||
Linear,
|
||||
@@ -130,8 +134,6 @@ struct ButtonStatus {
|
||||
bool inverted{};
|
||||
// Press once to activate, press again to release
|
||||
bool toggle{};
|
||||
// Spams the button when active
|
||||
bool turbo{};
|
||||
// Internal lock for the toggle status
|
||||
bool locked{};
|
||||
};
|
||||
@@ -188,8 +190,6 @@ struct TouchStatus {
|
||||
struct BodyColorStatus {
|
||||
u32 body{};
|
||||
u32 buttons{};
|
||||
u32 left_grip{};
|
||||
u32 right_grip{};
|
||||
};
|
||||
|
||||
// HD rumble data
|
||||
@@ -228,31 +228,17 @@ enum class ButtonNames {
|
||||
Engine,
|
||||
// This will display the button by value instead of the button name
|
||||
Value,
|
||||
|
||||
// Joycon button names
|
||||
ButtonLeft,
|
||||
ButtonRight,
|
||||
ButtonDown,
|
||||
ButtonUp,
|
||||
TriggerZ,
|
||||
TriggerR,
|
||||
TriggerL,
|
||||
ButtonA,
|
||||
ButtonB,
|
||||
ButtonX,
|
||||
ButtonY,
|
||||
ButtonPlus,
|
||||
ButtonMinus,
|
||||
ButtonHome,
|
||||
ButtonCapture,
|
||||
ButtonStickL,
|
||||
ButtonStickR,
|
||||
TriggerL,
|
||||
TriggerZL,
|
||||
TriggerSL,
|
||||
TriggerR,
|
||||
TriggerZR,
|
||||
TriggerSR,
|
||||
|
||||
// GC button names
|
||||
TriggerZ,
|
||||
ButtonStart,
|
||||
|
||||
// DS4 button names
|
||||
@@ -306,6 +292,9 @@ class InputDevice {
|
||||
public:
|
||||
virtual ~InputDevice() = default;
|
||||
|
||||
// Request input device to update if necessary
|
||||
virtual void SoftUpdate() {}
|
||||
|
||||
// Force input device to update data regardless of the current state
|
||||
virtual void ForceUpdate() {}
|
||||
|
||||
@@ -330,24 +319,22 @@ class OutputDevice {
|
||||
public:
|
||||
virtual ~OutputDevice() = default;
|
||||
|
||||
virtual DriverResult SetLED([[maybe_unused]] const LedStatus& led_status) {
|
||||
return DriverResult::NotSupported;
|
||||
}
|
||||
virtual void SetLED([[maybe_unused]] const LedStatus& led_status) {}
|
||||
|
||||
virtual DriverResult SetVibration([[maybe_unused]] const VibrationStatus& vibration_status) {
|
||||
return DriverResult::NotSupported;
|
||||
virtual VibrationError SetVibration([[maybe_unused]] const VibrationStatus& vibration_status) {
|
||||
return VibrationError::NotSupported;
|
||||
}
|
||||
|
||||
virtual bool IsVibrationEnabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual DriverResult SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
|
||||
return DriverResult::NotSupported;
|
||||
virtual PollingError SetPollingMode([[maybe_unused]] PollingMode polling_mode) {
|
||||
return PollingError::NotSupported;
|
||||
}
|
||||
|
||||
virtual DriverResult SetCameraFormat([[maybe_unused]] CameraFormat camera_format) {
|
||||
return DriverResult::NotSupported;
|
||||
virtual CameraError SetCameraFormat([[maybe_unused]] CameraFormat camera_format) {
|
||||
return CameraError::NotSupported;
|
||||
}
|
||||
|
||||
virtual NfcState SupportsNfc() const {
|
||||
|
||||
@@ -242,21 +242,19 @@ public:
|
||||
|
||||
template <typename T>
|
||||
concept HasRedBlackKeyType = requires {
|
||||
{
|
||||
std::is_same<typename T::RedBlackKeyType, void>::value
|
||||
} -> std::convertible_to<bool>;
|
||||
};
|
||||
{ std::is_same<typename T::RedBlackKeyType, void>::value } -> std::convertible_to<bool>;
|
||||
};
|
||||
|
||||
namespace impl {
|
||||
|
||||
template <typename T, typename Default>
|
||||
consteval auto* GetRedBlackKeyType() {
|
||||
if constexpr (HasRedBlackKeyType<T>) {
|
||||
return static_cast<typename T::RedBlackKeyType*>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default*>(nullptr);
|
||||
template <typename T, typename Default>
|
||||
consteval auto* GetRedBlackKeyType() {
|
||||
if constexpr (HasRedBlackKeyType<T>) {
|
||||
return static_cast<typename T::RedBlackKeyType*>(nullptr);
|
||||
} else {
|
||||
return static_cast<Default*>(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace impl
|
||||
|
||||
|
||||
@@ -119,7 +119,7 @@ bool ParseFilterRule(Filter& instance, Iterator begin, Iterator end) {
|
||||
SUB(Service, NPNS) \
|
||||
SUB(Service, NS) \
|
||||
SUB(Service, NVDRV) \
|
||||
SUB(Service, Nvnflinger) \
|
||||
SUB(Service, NVFlinger) \
|
||||
SUB(Service, OLSC) \
|
||||
SUB(Service, PCIE) \
|
||||
SUB(Service, PCTL) \
|
||||
|
||||
+101
-101
@@ -29,107 +29,107 @@ enum class Level : u8 {
|
||||
* filter.cpp.
|
||||
*/
|
||||
enum class Class : u8 {
|
||||
Log, ///< Messages about the log system itself
|
||||
Common, ///< Library routines
|
||||
Common_Filesystem, ///< Filesystem interface library
|
||||
Common_Memory, ///< Memory mapping and management functions
|
||||
Core, ///< LLE emulation core
|
||||
Core_ARM, ///< ARM CPU core
|
||||
Core_Timing, ///< CoreTiming functions
|
||||
Config, ///< Emulator configuration (including commandline)
|
||||
Debug, ///< Debugging tools
|
||||
Debug_Emulated, ///< Debug messages from the emulated programs
|
||||
Debug_GPU, ///< GPU debugging tools
|
||||
Debug_Breakpoint, ///< Logging breakpoints and watchpoints
|
||||
Debug_GDBStub, ///< GDB Stub
|
||||
Kernel, ///< The HLE implementation of the CTR kernel
|
||||
Kernel_SVC, ///< Kernel system calls
|
||||
Service, ///< HLE implementation of system services. Each major service
|
||||
///< should have its own subclass.
|
||||
Service_ACC, ///< The ACC (Accounts) service
|
||||
Service_AM, ///< The AM (Applet manager) service
|
||||
Service_AOC, ///< The AOC (AddOn Content) service
|
||||
Service_APM, ///< The APM (Performance) service
|
||||
Service_ARP, ///< The ARP service
|
||||
Service_Audio, ///< The Audio (Audio control) service
|
||||
Service_BCAT, ///< The BCAT service
|
||||
Service_BGTC, ///< The BGTC (Background Task Controller) service
|
||||
Service_BPC, ///< The BPC service
|
||||
Service_BTDRV, ///< The Bluetooth driver service
|
||||
Service_BTM, ///< The BTM service
|
||||
Service_Capture, ///< The capture service
|
||||
Service_ERPT, ///< The error reporting service
|
||||
Service_ETicket, ///< The ETicket service
|
||||
Service_EUPLD, ///< The error upload service
|
||||
Service_Fatal, ///< The Fatal service
|
||||
Service_FGM, ///< The FGM service
|
||||
Service_Friend, ///< The friend service
|
||||
Service_FS, ///< The FS (Filesystem) service
|
||||
Service_GRC, ///< The game recording service
|
||||
Service_HID, ///< The HID (Human interface device) service
|
||||
Service_IRS, ///< The IRS service
|
||||
Service_JIT, ///< The JIT service
|
||||
Service_LBL, ///< The LBL (LCD backlight) service
|
||||
Service_LDN, ///< The LDN (Local domain network) service
|
||||
Service_LDR, ///< The loader service
|
||||
Service_LM, ///< The LM (Logger) service
|
||||
Service_Migration, ///< The migration service
|
||||
Service_Mii, ///< The Mii service
|
||||
Service_MM, ///< The MM (Multimedia) service
|
||||
Service_MNPP, ///< The MNPP service
|
||||
Service_NCM, ///< The NCM service
|
||||
Service_NFC, ///< The NFC (Near-field communication) service
|
||||
Service_NFP, ///< The NFP service
|
||||
Service_NGCT, ///< The NGCT (No Good Content for Terra) service
|
||||
Service_NIFM, ///< The NIFM (Network interface) service
|
||||
Service_NIM, ///< The NIM service
|
||||
Service_NOTIF, ///< The NOTIF (Notification) service
|
||||
Service_NPNS, ///< The NPNS service
|
||||
Service_NS, ///< The NS services
|
||||
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
|
||||
Service_Nvnflinger, ///< The Nvnflinger service
|
||||
Service_OLSC, ///< The OLSC service
|
||||
Service_PCIE, ///< The PCIe service
|
||||
Service_PCTL, ///< The PCTL (Parental control) service
|
||||
Service_PCV, ///< The PCV service
|
||||
Service_PM, ///< The PM service
|
||||
Service_PREPO, ///< The PREPO (Play report) service
|
||||
Service_PSC, ///< The PSC service
|
||||
Service_PTM, ///< The PTM service
|
||||
Service_SET, ///< The SET (Settings) service
|
||||
Service_SM, ///< The SM (Service manager) service
|
||||
Service_SPL, ///< The SPL service
|
||||
Service_SSL, ///< The SSL service
|
||||
Service_TCAP, ///< The TCAP service.
|
||||
Service_Time, ///< The time service
|
||||
Service_USB, ///< The USB (Universal Serial Bus) service
|
||||
Service_VI, ///< The VI (Video interface) service
|
||||
Service_WLAN, ///< The WLAN (Wireless local area network) service
|
||||
HW, ///< Low-level hardware emulation
|
||||
HW_Memory, ///< Memory-map and address translation
|
||||
HW_LCD, ///< LCD register emulation
|
||||
HW_GPU, ///< GPU control emulation
|
||||
HW_AES, ///< AES engine emulation
|
||||
IPC, ///< IPC interface
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Emulator video output and hardware acceleration
|
||||
Render_Software, ///< Software renderer backend
|
||||
Render_OpenGL, ///< OpenGL backend
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
Shader, ///< Shader recompiler
|
||||
Shader_SPIRV, ///< Shader SPIR-V code generation
|
||||
Shader_GLASM, ///< Shader GLASM code generation
|
||||
Shader_GLSL, ///< Shader GLSL code generation
|
||||
Audio, ///< Audio emulation
|
||||
Audio_DSP, ///< The HLE implementation of the DSP
|
||||
Audio_Sink, ///< Emulator audio output backend
|
||||
Loader, ///< ROM loader
|
||||
CheatEngine, ///< Memory manipulation and engine VM functions
|
||||
Crypto, ///< Cryptographic engine/functions
|
||||
Input, ///< Input emulation
|
||||
Network, ///< Network emulation
|
||||
WebService, ///< Interface to yuzu Web Services
|
||||
Count ///< Total number of logging classes
|
||||
Log, ///< Messages about the log system itself
|
||||
Common, ///< Library routines
|
||||
Common_Filesystem, ///< Filesystem interface library
|
||||
Common_Memory, ///< Memory mapping and management functions
|
||||
Core, ///< LLE emulation core
|
||||
Core_ARM, ///< ARM CPU core
|
||||
Core_Timing, ///< CoreTiming functions
|
||||
Config, ///< Emulator configuration (including commandline)
|
||||
Debug, ///< Debugging tools
|
||||
Debug_Emulated, ///< Debug messages from the emulated programs
|
||||
Debug_GPU, ///< GPU debugging tools
|
||||
Debug_Breakpoint, ///< Logging breakpoints and watchpoints
|
||||
Debug_GDBStub, ///< GDB Stub
|
||||
Kernel, ///< The HLE implementation of the CTR kernel
|
||||
Kernel_SVC, ///< Kernel system calls
|
||||
Service, ///< HLE implementation of system services. Each major service
|
||||
///< should have its own subclass.
|
||||
Service_ACC, ///< The ACC (Accounts) service
|
||||
Service_AM, ///< The AM (Applet manager) service
|
||||
Service_AOC, ///< The AOC (AddOn Content) service
|
||||
Service_APM, ///< The APM (Performance) service
|
||||
Service_ARP, ///< The ARP service
|
||||
Service_Audio, ///< The Audio (Audio control) service
|
||||
Service_BCAT, ///< The BCAT service
|
||||
Service_BGTC, ///< The BGTC (Background Task Controller) service
|
||||
Service_BPC, ///< The BPC service
|
||||
Service_BTDRV, ///< The Bluetooth driver service
|
||||
Service_BTM, ///< The BTM service
|
||||
Service_Capture, ///< The capture service
|
||||
Service_ERPT, ///< The error reporting service
|
||||
Service_ETicket, ///< The ETicket service
|
||||
Service_EUPLD, ///< The error upload service
|
||||
Service_Fatal, ///< The Fatal service
|
||||
Service_FGM, ///< The FGM service
|
||||
Service_Friend, ///< The friend service
|
||||
Service_FS, ///< The FS (Filesystem) service
|
||||
Service_GRC, ///< The game recording service
|
||||
Service_HID, ///< The HID (Human interface device) service
|
||||
Service_IRS, ///< The IRS service
|
||||
Service_JIT, ///< The JIT service
|
||||
Service_LBL, ///< The LBL (LCD backlight) service
|
||||
Service_LDN, ///< The LDN (Local domain network) service
|
||||
Service_LDR, ///< The loader service
|
||||
Service_LM, ///< The LM (Logger) service
|
||||
Service_Migration, ///< The migration service
|
||||
Service_Mii, ///< The Mii service
|
||||
Service_MM, ///< The MM (Multimedia) service
|
||||
Service_MNPP, ///< The MNPP service
|
||||
Service_NCM, ///< The NCM service
|
||||
Service_NFC, ///< The NFC (Near-field communication) service
|
||||
Service_NFP, ///< The NFP service
|
||||
Service_NGCT, ///< The NGCT (No Good Content for Terra) service
|
||||
Service_NIFM, ///< The NIFM (Network interface) service
|
||||
Service_NIM, ///< The NIM service
|
||||
Service_NOTIF, ///< The NOTIF (Notification) service
|
||||
Service_NPNS, ///< The NPNS service
|
||||
Service_NS, ///< The NS services
|
||||
Service_NVDRV, ///< The NVDRV (Nvidia driver) service
|
||||
Service_NVFlinger, ///< The NVFlinger service
|
||||
Service_OLSC, ///< The OLSC service
|
||||
Service_PCIE, ///< The PCIe service
|
||||
Service_PCTL, ///< The PCTL (Parental control) service
|
||||
Service_PCV, ///< The PCV service
|
||||
Service_PM, ///< The PM service
|
||||
Service_PREPO, ///< The PREPO (Play report) service
|
||||
Service_PSC, ///< The PSC service
|
||||
Service_PTM, ///< The PTM service
|
||||
Service_SET, ///< The SET (Settings) service
|
||||
Service_SM, ///< The SM (Service manager) service
|
||||
Service_SPL, ///< The SPL service
|
||||
Service_SSL, ///< The SSL service
|
||||
Service_TCAP, ///< The TCAP service.
|
||||
Service_Time, ///< The time service
|
||||
Service_USB, ///< The USB (Universal Serial Bus) service
|
||||
Service_VI, ///< The VI (Video interface) service
|
||||
Service_WLAN, ///< The WLAN (Wireless local area network) service
|
||||
HW, ///< Low-level hardware emulation
|
||||
HW_Memory, ///< Memory-map and address translation
|
||||
HW_LCD, ///< LCD register emulation
|
||||
HW_GPU, ///< GPU control emulation
|
||||
HW_AES, ///< AES engine emulation
|
||||
IPC, ///< IPC interface
|
||||
Frontend, ///< Emulator UI
|
||||
Render, ///< Emulator video output and hardware acceleration
|
||||
Render_Software, ///< Software renderer backend
|
||||
Render_OpenGL, ///< OpenGL backend
|
||||
Render_Vulkan, ///< Vulkan backend
|
||||
Shader, ///< Shader recompiler
|
||||
Shader_SPIRV, ///< Shader SPIR-V code generation
|
||||
Shader_GLASM, ///< Shader GLASM code generation
|
||||
Shader_GLSL, ///< Shader GLSL code generation
|
||||
Audio, ///< Audio emulation
|
||||
Audio_DSP, ///< The HLE implementation of the DSP
|
||||
Audio_Sink, ///< Emulator audio output backend
|
||||
Loader, ///< ROM loader
|
||||
CheatEngine, ///< Memory manipulation and engine VM functions
|
||||
Crypto, ///< Cryptographic engine/functions
|
||||
Input, ///< Input emulation
|
||||
Network, ///< Network emulation
|
||||
WebService, ///< Interface to yuzu Web Services
|
||||
Count ///< Total number of logging classes
|
||||
};
|
||||
|
||||
} // namespace Common::Log
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <class T>
|
||||
requires(!std::is_array_v<T>)
|
||||
std::unique_ptr<T> make_unique_for_overwrite() {
|
||||
return std::unique_ptr<T>(new T);
|
||||
}
|
||||
|
||||
template <class T>
|
||||
requires std::is_unbounded_array_v<T>
|
||||
std::unique_ptr<T> make_unique_for_overwrite(std::size_t n) {
|
||||
return std::unique_ptr<T>(new std::remove_extent_t<T>[n]);
|
||||
}
|
||||
|
||||
template <class T, class... Args>
|
||||
requires std::is_bounded_array_v<T>
|
||||
void make_unique_for_overwrite(Args&&...) = delete;
|
||||
|
||||
} // namespace Common
|
||||
@@ -18,9 +18,9 @@ namespace ranges {
|
||||
|
||||
template <typename T>
|
||||
concept range = requires(T& t) {
|
||||
begin(t);
|
||||
end(t);
|
||||
};
|
||||
begin(t);
|
||||
end(t);
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
concept input_range = range<T>;
|
||||
@@ -421,7 +421,7 @@ struct generate_fn {
|
||||
}
|
||||
|
||||
template <typename R, std::copy_constructible F>
|
||||
requires std::invocable<F&> && ranges::output_range<R>
|
||||
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));
|
||||
}
|
||||
|
||||
@@ -11,8 +11,6 @@
|
||||
|
||||
#ifdef __cpp_lib_jthread
|
||||
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <stop_token>
|
||||
#include <thread>
|
||||
|
||||
@@ -23,36 +21,23 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred&& pred) {
|
||||
cv.wait(lock, token, std::move(pred));
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, Period>& rel_time) {
|
||||
std::condition_variable_any cv;
|
||||
std::mutex m;
|
||||
|
||||
// Perform the timed wait.
|
||||
std::unique_lock lk{m};
|
||||
return !cv.wait_for(lk, token, rel_time, [&] { return token.stop_requested(); });
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
#else
|
||||
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <optional>
|
||||
#include <thread>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
namespace std {
|
||||
namespace polyfill {
|
||||
|
||||
using stop_state_callback = size_t;
|
||||
using stop_state_callbacks = list<function<void()>>;
|
||||
|
||||
class stop_state {
|
||||
public:
|
||||
@@ -60,69 +45,61 @@ public:
|
||||
~stop_state() = default;
|
||||
|
||||
bool request_stop() {
|
||||
unique_lock lk{m_lock};
|
||||
stop_state_callbacks callbacks;
|
||||
|
||||
if (m_stop_requested) {
|
||||
// Already set, nothing to do.
|
||||
return false;
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
// Mark stop requested.
|
||||
m_stop_requested = true;
|
||||
|
||||
while (!m_callbacks.empty()) {
|
||||
// Get an iterator to the first element.
|
||||
const auto it = m_callbacks.begin();
|
||||
|
||||
// Move the callback function out of the map.
|
||||
function<void()> f;
|
||||
swap(it->second, f);
|
||||
|
||||
// Erase the now-empty map element.
|
||||
m_callbacks.erase(it);
|
||||
|
||||
// Run the callback.
|
||||
if (f) {
|
||||
f();
|
||||
}
|
||||
for (auto callback : callbacks) {
|
||||
callback();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool stop_requested() const {
|
||||
unique_lock lk{m_lock};
|
||||
return m_stop_requested;
|
||||
return m_stop_requested.load();
|
||||
}
|
||||
|
||||
stop_state_callback insert_callback(function<void()> f) {
|
||||
unique_lock lk{m_lock};
|
||||
stop_state_callbacks::const_iterator insert_callback(function<void()> f) {
|
||||
stop_state_callbacks::const_iterator ret{};
|
||||
bool should_run{};
|
||||
|
||||
if (m_stop_requested) {
|
||||
// Stop already requested. Don't insert anything,
|
||||
// just run the callback synchronously.
|
||||
if (f) {
|
||||
f();
|
||||
}
|
||||
return 0;
|
||||
{
|
||||
scoped_lock lk{m_lock};
|
||||
should_run = m_stop_requested.load();
|
||||
m_callbacks.push_front(f);
|
||||
ret = m_callbacks.begin();
|
||||
}
|
||||
|
||||
if (should_run) {
|
||||
f();
|
||||
}
|
||||
|
||||
// Insert the callback.
|
||||
stop_state_callback ret = ++m_next_callback;
|
||||
m_callbacks.emplace(ret, move(f));
|
||||
return ret;
|
||||
}
|
||||
|
||||
void remove_callback(stop_state_callback cb) {
|
||||
unique_lock lk{m_lock};
|
||||
m_callbacks.erase(cb);
|
||||
void remove_callback(stop_state_callbacks::const_iterator it) {
|
||||
scoped_lock lk{m_lock};
|
||||
m_callbacks.erase(it);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable recursive_mutex m_lock;
|
||||
map<stop_state_callback, function<void()>> m_callbacks;
|
||||
stop_state_callback m_next_callback{0};
|
||||
bool m_stop_requested{false};
|
||||
mutex m_lock;
|
||||
atomic<bool> m_stop_requested;
|
||||
stop_state_callbacks m_callbacks;
|
||||
};
|
||||
|
||||
} // namespace polyfill
|
||||
@@ -213,7 +190,7 @@ public:
|
||||
using callback_type = Callback;
|
||||
|
||||
template <typename C>
|
||||
requires constructible_from<Callback, 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) {
|
||||
@@ -222,7 +199,7 @@ public:
|
||||
}
|
||||
}
|
||||
template <typename C>
|
||||
requires constructible_from<Callback, 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)) {
|
||||
@@ -232,7 +209,7 @@ public:
|
||||
}
|
||||
~stop_callback() {
|
||||
if (m_stop_state && m_callback) {
|
||||
m_stop_state->remove_callback(m_callback);
|
||||
m_stop_state->remove_callback(*m_callback);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -243,7 +220,7 @@ public:
|
||||
|
||||
private:
|
||||
shared_ptr<polyfill::stop_state> m_stop_state;
|
||||
polyfill::stop_state_callback m_callback;
|
||||
optional<polyfill::stop_state_callbacks::const_iterator> m_callback;
|
||||
};
|
||||
|
||||
template <typename Callback>
|
||||
@@ -341,28 +318,6 @@ void CondvarWait(Condvar& cv, Lock& lock, std::stop_token token, Pred pred) {
|
||||
cv.wait(lock, [&] { return pred() || token.stop_requested(); });
|
||||
}
|
||||
|
||||
template <typename Rep, typename Period>
|
||||
bool StoppableTimedWait(std::stop_token token, const std::chrono::duration<Rep, Period>& rel_time) {
|
||||
if (token.stop_requested()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool stop_requested = false;
|
||||
std::condition_variable cv;
|
||||
std::mutex m;
|
||||
|
||||
std::stop_callback cb(token, [&] {
|
||||
// Wake up the waiting thread.
|
||||
std::unique_lock lk{m};
|
||||
stop_requested = true;
|
||||
cv.notify_one();
|
||||
});
|
||||
|
||||
// Perform the timed wait.
|
||||
std::unique_lock lk{m};
|
||||
return !cv.wait_for(lk, rel_time, [&] { return stop_requested; });
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <type_traits>
|
||||
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
template <typename KeyTBase, typename ValueT>
|
||||
class RangeMap {
|
||||
private:
|
||||
using KeyT =
|
||||
std::conditional_t<std::is_signed_v<KeyTBase>, KeyTBase, std::make_signed_t<KeyTBase>>;
|
||||
|
||||
public:
|
||||
explicit RangeMap(ValueT null_value_) : null_value{null_value_} {
|
||||
container.emplace(std::numeric_limits<KeyT>::min(), null_value);
|
||||
};
|
||||
~RangeMap() = default;
|
||||
|
||||
void Map(KeyTBase address, KeyTBase address_end, ValueT value) {
|
||||
KeyT new_address = static_cast<KeyT>(address);
|
||||
KeyT new_address_end = static_cast<KeyT>(address_end);
|
||||
if (new_address < 0) {
|
||||
new_address = 0;
|
||||
}
|
||||
if (new_address_end < 0) {
|
||||
new_address_end = 0;
|
||||
}
|
||||
InternalMap(new_address, new_address_end, value);
|
||||
}
|
||||
|
||||
void Unmap(KeyTBase address, KeyTBase address_end) {
|
||||
Map(address, address_end, null_value);
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t GetContinousSizeFrom(KeyTBase address) const {
|
||||
const KeyT new_address = static_cast<KeyT>(address);
|
||||
if (new_address < 0) {
|
||||
return 0;
|
||||
}
|
||||
return ContinousSizeInternal(new_address);
|
||||
}
|
||||
|
||||
[[nodiscard]] ValueT GetValueAt(KeyT address) const {
|
||||
const KeyT new_address = static_cast<KeyT>(address);
|
||||
if (new_address < 0) {
|
||||
return null_value;
|
||||
}
|
||||
return GetValueInternal(new_address);
|
||||
}
|
||||
|
||||
private:
|
||||
using MapType = std::map<KeyT, ValueT>;
|
||||
using IteratorType = typename MapType::iterator;
|
||||
using ConstIteratorType = typename MapType::const_iterator;
|
||||
|
||||
size_t ContinousSizeInternal(KeyT address) const {
|
||||
const auto it = GetFirstElementBeforeOrOn(address);
|
||||
if (it == container.end() || it->second == null_value) {
|
||||
return 0;
|
||||
}
|
||||
const auto it_end = std::next(it);
|
||||
if (it_end == container.end()) {
|
||||
return std::numeric_limits<KeyT>::max() - address;
|
||||
}
|
||||
return it_end->first - address;
|
||||
}
|
||||
|
||||
ValueT GetValueInternal(KeyT address) const {
|
||||
const auto it = GetFirstElementBeforeOrOn(address);
|
||||
if (it == container.end()) {
|
||||
return null_value;
|
||||
}
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ConstIteratorType GetFirstElementBeforeOrOn(KeyT address) const {
|
||||
auto it = container.lower_bound(address);
|
||||
if (it == container.begin()) {
|
||||
return it;
|
||||
}
|
||||
if (it != container.end() && (it->first == address)) {
|
||||
return it;
|
||||
}
|
||||
--it;
|
||||
return it;
|
||||
}
|
||||
|
||||
ValueT GetFirstValueWithin(KeyT address) {
|
||||
auto it = container.lower_bound(address);
|
||||
if (it == container.begin()) {
|
||||
return it->second;
|
||||
}
|
||||
if (it == container.end()) [[unlikely]] { // this would be a bug
|
||||
return null_value;
|
||||
}
|
||||
--it;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
ValueT GetLastValueWithin(KeyT address) {
|
||||
auto it = container.upper_bound(address);
|
||||
if (it == container.end()) {
|
||||
return null_value;
|
||||
}
|
||||
if (it == container.begin()) [[unlikely]] { // this would be a bug
|
||||
return it->second;
|
||||
}
|
||||
--it;
|
||||
return it->second;
|
||||
}
|
||||
|
||||
void InternalMap(KeyT address, KeyT address_end, ValueT value) {
|
||||
const bool must_add_start = GetFirstValueWithin(address) != value;
|
||||
const ValueT last_value = GetLastValueWithin(address_end);
|
||||
const bool must_add_end = last_value != value;
|
||||
auto it = container.lower_bound(address);
|
||||
const auto it_end = container.upper_bound(address_end);
|
||||
while (it != it_end) {
|
||||
it = container.erase(it);
|
||||
}
|
||||
if (must_add_start) {
|
||||
container.emplace(address, value);
|
||||
}
|
||||
if (must_add_end) {
|
||||
container.emplace(address_end, last_value);
|
||||
}
|
||||
}
|
||||
|
||||
ValueT null_value;
|
||||
MapType container;
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
@@ -1,96 +0,0 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "common/make_unique_for_overwrite.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/**
|
||||
* ScratchBuffer class
|
||||
* This class creates a default initialized heap allocated buffer for cases such as intermediate
|
||||
* buffers being copied into entirely, where value initializing members during allocation or resize
|
||||
* is redundant.
|
||||
*/
|
||||
template <typename T>
|
||||
class ScratchBuffer {
|
||||
public:
|
||||
ScratchBuffer() = default;
|
||||
|
||||
explicit ScratchBuffer(size_t initial_capacity)
|
||||
: last_requested_size{initial_capacity}, buffer_capacity{initial_capacity},
|
||||
buffer{Common::make_unique_for_overwrite<T[]>(initial_capacity)} {}
|
||||
|
||||
~ScratchBuffer() = default;
|
||||
ScratchBuffer(ScratchBuffer&&) = default;
|
||||
|
||||
/// This will only grow the buffer's capacity if size is greater than the current capacity.
|
||||
/// The previously held data will remain intact.
|
||||
void resize(size_t size) {
|
||||
if (size > buffer_capacity) {
|
||||
auto new_buffer = Common::make_unique_for_overwrite<T[]>(size);
|
||||
std::move(buffer.get(), buffer.get() + buffer_capacity, new_buffer.get());
|
||||
buffer = std::move(new_buffer);
|
||||
buffer_capacity = size;
|
||||
}
|
||||
last_requested_size = size;
|
||||
}
|
||||
|
||||
/// This will only grow the buffer's capacity if size is greater than the current capacity.
|
||||
/// The previously held data will be destroyed if a reallocation occurs.
|
||||
void resize_destructive(size_t size) {
|
||||
if (size > buffer_capacity) {
|
||||
buffer_capacity = size;
|
||||
buffer = Common::make_unique_for_overwrite<T[]>(buffer_capacity);
|
||||
}
|
||||
last_requested_size = size;
|
||||
}
|
||||
|
||||
[[nodiscard]] T* data() noexcept {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* data() const noexcept {
|
||||
return buffer.get();
|
||||
}
|
||||
|
||||
[[nodiscard]] T* begin() noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* begin() const noexcept {
|
||||
return data();
|
||||
}
|
||||
|
||||
[[nodiscard]] T* end() noexcept {
|
||||
return data() + last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T* end() const noexcept {
|
||||
return data() + last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] T& operator[](size_t i) {
|
||||
return buffer[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](size_t i) const {
|
||||
return buffer[i];
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept {
|
||||
return last_requested_size;
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t capacity() const noexcept {
|
||||
return buffer_capacity;
|
||||
}
|
||||
|
||||
private:
|
||||
size_t last_requested_size{};
|
||||
size_t buffer_capacity{};
|
||||
std::unique_ptr<T[]> buffer{};
|
||||
};
|
||||
|
||||
} // namespace Common
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user