mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-16 13:22:41 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f1fdb389a4 | |||
| 21bb1b8210 |
@@ -52,7 +52,7 @@ jobs:
|
||||
}
|
||||
EOF
|
||||
|
||||
curl -XPOST \
|
||||
curl -X 'POST' \
|
||||
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
|
||||
-H 'accept: application/json' \
|
||||
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: Update Dependencies
|
||||
name: update-deps
|
||||
|
||||
on:
|
||||
# saturday at noon
|
||||
@@ -7,7 +7,7 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
update-deps:
|
||||
tx-update:
|
||||
runs-on: source
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -24,21 +24,18 @@ jobs:
|
||||
git remote set-url origin ci:eden-emu/eden.git
|
||||
|
||||
DATE=$(date +"%b %d")
|
||||
TIMESTAMP=$(date +"%s")
|
||||
echo "DATE=$DATE" >> "$GITHUB_ENV"
|
||||
echo "TIMESTAMP=$TIMESTAMP" >> "$GITHUB_ENV"
|
||||
|
||||
git switch -c update-deps-$TIMESTAMP
|
||||
git switch -c update-deps-$DATE
|
||||
tools/cpmutil.sh package update -ac
|
||||
git push
|
||||
|
||||
- name: Create PR
|
||||
run: |
|
||||
set -x
|
||||
TITLE="[externals] Dependency update for $DATE"
|
||||
BODY="$(git show -s --format='%b')"
|
||||
BASE=master
|
||||
HEAD=update-deps-$TIMESTAMP
|
||||
HEAD=update-deps-$DATE
|
||||
|
||||
cat << EOF > data.json
|
||||
{
|
||||
@@ -49,7 +46,7 @@ jobs:
|
||||
}
|
||||
EOF
|
||||
|
||||
curl -XPOST \
|
||||
curl -X 'POST' \
|
||||
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
|
||||
-H 'accept: application/json' \
|
||||
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
From 509be32bbfa6eb95014860f7c9ea6d45c8ddaa56 Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sun, 8 Mar 2026 15:11:12 -0400
|
||||
Subject: [PATCH] [cmake] Simplify zstd find logic, and support pre-existing
|
||||
zstd target
|
||||
|
||||
Some deduplication work on the zstd required/if-available logic. Also
|
||||
adds support for pre-existing `zstd::libzstd` which is useful for
|
||||
projects that bundle their own zstd in a way that doesn't get caught by
|
||||
`CONFIG`
|
||||
|
||||
Signed-off-by: crueter <crueter@eden-emu.dev>
|
||||
---
|
||||
CMakeLists.txt | 46 ++++++++++++++++++++++++++--------------------
|
||||
1 file changed, 26 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 1874e36be0..8d31198006 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -241,28 +241,34 @@ endif()
|
||||
# NOTE:
|
||||
# zstd < 1.5.6 does not provide the CMake imported target `zstd::libzstd`.
|
||||
# Older versions must be consumed via their pkg-config file.
|
||||
-if(HTTPLIB_REQUIRE_ZSTD)
|
||||
- find_package(zstd 1.5.6 CONFIG)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig REQUIRED)
|
||||
- pkg_check_modules(zstd REQUIRED IMPORTED_TARGET libzstd)
|
||||
- add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
- endif()
|
||||
- set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
-elseif(HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
- find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
- if(NOT zstd_FOUND)
|
||||
- find_package(PkgConfig QUIET)
|
||||
- if(PKG_CONFIG_FOUND)
|
||||
- pkg_check_modules(zstd QUIET IMPORTED_TARGET libzstd)
|
||||
-
|
||||
- if(TARGET PkgConfig::zstd)
|
||||
+if (HTTPLIB_REQUIRE_ZSTD)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED REQUIRED)
|
||||
+elseif (HTTPLIB_USE_ZSTD_IF_AVAILABLE)
|
||||
+ set(HTTPLIB_ZSTD_REQUESTED ON)
|
||||
+ set(HTTPLIB_ZSTD_REQUIRED QUIET)
|
||||
+endif()
|
||||
+
|
||||
+if (HTTPLIB_ZSTD_REQUESTED)
|
||||
+ if (TARGET zstd::libzstd)
|
||||
+ set(HTTPLIB_IS_USING_ZSTD TRUE)
|
||||
+ else()
|
||||
+ find_package(zstd 1.5.6 CONFIG QUIET)
|
||||
+
|
||||
+ if (NOT zstd_FOUND)
|
||||
+ find_package(PkgConfig ${HTTPLIB_ZSTD_REQUIRED})
|
||||
+ pkg_check_modules(zstd ${HTTPLIB_ZSTD_REQUIRED} IMPORTED_TARGET libzstd)
|
||||
+
|
||||
+ if (TARGET PkgConfig::zstd)
|
||||
add_library(zstd::libzstd ALIAS PkgConfig::zstd)
|
||||
endif()
|
||||
endif()
|
||||
+
|
||||
+ # This will always be true if zstd is required.
|
||||
+ # If zstd *isn't* found when zstd is set to required,
|
||||
+ # CMake will error out earlier in this block.
|
||||
+ set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
- # Both find_package and PkgConf set a XXX_FOUND var
|
||||
- set(HTTPLIB_IS_USING_ZSTD ${zstd_FOUND})
|
||||
endif()
|
||||
|
||||
# Used for default, common dirs that the end-user can change (if needed)
|
||||
@@ -317,13 +323,13 @@ if(HTTPLIB_COMPILE)
|
||||
$<BUILD_INTERFACE:${_httplib_build_includedir}/httplib.h>
|
||||
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/httplib.h>
|
||||
)
|
||||
-
|
||||
+
|
||||
# Add C++20 module support if requested
|
||||
# Include from separate file to prevent parse errors on older CMake versions
|
||||
if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.28")
|
||||
include(cmake/modules.cmake)
|
||||
endif()
|
||||
-
|
||||
+
|
||||
set_target_properties(${PROJECT_NAME}
|
||||
PROPERTIES
|
||||
VERSION ${${PROJECT_NAME}_VERSION}
|
||||
@@ -1,214 +0,0 @@
|
||||
From ec4c1fdf526cb9ad045abf59b29ee495bbf5023a Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sat, 30 May 2026 20:56:35 -0400
|
||||
Subject: [PATCH] cpmutil compat
|
||||
|
||||
---
|
||||
CMakeLists.txt | 31 ++++++++-----------
|
||||
cmake/FetchOpenSSL.cmake | 64 ----------------------------------------
|
||||
cmake/GetCPM.cmake | 5 ----
|
||||
3 files changed, 13 insertions(+), 87 deletions(-)
|
||||
delete mode 100644 cmake/FetchOpenSSL.cmake
|
||||
delete mode 100644 cmake/GetCPM.cmake
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 5420ecc..9ffd5a0 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -19,9 +19,7 @@ include(FetchContent)
|
||||
include(ProcessorCount)
|
||||
include(cmake/ConfigureOpenSSL.cmake)
|
||||
include(cmake/DetectTargetPlatform.cmake)
|
||||
-include(cmake/FetchOpenSSL.cmake)
|
||||
include(cmake/FindVcvarsall.cmake)
|
||||
-include(cmake/GetCPM.cmake)
|
||||
|
||||
# Custom options
|
||||
option(OPENSSL_BUILD_VERBOSE "Enable verbose output from build" OFF)
|
||||
@@ -47,9 +45,6 @@ if("${OPENSSL_TARGET_PLATFORM}" STREQUAL "")
|
||||
detect_target_platform(OPENSSL_TARGET_PLATFORM)
|
||||
endif()
|
||||
|
||||
-# Fetch OpenSSL source
|
||||
-fetch_openssl()
|
||||
-
|
||||
# Apply patches
|
||||
foreach(patch IN LISTS OPENSSL_PATCH)
|
||||
if(EXISTS "${patch}" AND NOT IS_DIRECTORY "${patch}")
|
||||
@@ -59,13 +54,13 @@ foreach(patch IN LISTS OPENSSL_PATCH)
|
||||
|
||||
execute_process(
|
||||
COMMAND git init
|
||||
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
|
||||
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET
|
||||
)
|
||||
execute_process(
|
||||
COMMAND git apply ${patch}
|
||||
- WORKING_DIRECTORY ${openssl_SOURCE_DIR}
|
||||
+ WORKING_DIRECTORY ${OpenSSL_SOURCE_DIR}
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET
|
||||
)
|
||||
@@ -161,8 +156,8 @@ list(PREPEND OPENSSL_CONFIGURE_OPTIONS ${OPENSSL_TARGET_PLATFORM})
|
||||
# Configure OpenSSL
|
||||
configure_openssl(
|
||||
COMMAND ${VCVARSALL_COMMAND}
|
||||
- FILE ${openssl_SOURCE_DIR}/Configure
|
||||
- BUILD_DIR ${openssl_BINARY_DIR}
|
||||
+ FILE ${OpenSSL_SOURCE_DIR}/Configure
|
||||
+ BUILD_DIR ${OpenSSL_BINARY_DIR}
|
||||
OPTIONS ${OPENSSL_CONFIGURE_OPTIONS}
|
||||
)
|
||||
|
||||
@@ -203,8 +198,8 @@ endif()
|
||||
# Parse Makefile
|
||||
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_LIBS" OPENSSL_STATIC_LIBS)
|
||||
parse_makefile(${OPENSSL_MAKEFILE} "INSTALL_SHLIBS" OPENSSL_SHARED_LIBS)
|
||||
-list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${openssl_BINARY_DIR}/")
|
||||
-list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${openssl_BINARY_DIR}/")
|
||||
+list(TRANSFORM OPENSSL_STATIC_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
|
||||
+list(TRANSFORM OPENSSL_SHARED_LIBS PREPEND "${OpenSSL_BINARY_DIR}/")
|
||||
|
||||
foreach(LIBRARY IN LISTS OPENSSL_STATIC_LIBS)
|
||||
if(LIBRARY MATCHES "crypto")
|
||||
@@ -239,14 +234,14 @@ endif()
|
||||
|
||||
# Provide same targets and variables as FindOpenSSL module
|
||||
set(OPENSSL_FOUND ON CACHE BOOL "Override FindOpenSSL variables" FORCE)
|
||||
-set(OPENSSL_INCLUDE_DIR ${openssl_SOURCE_DIR}/include ${openssl_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
+set(OPENSSL_INCLUDE_DIR ${OpenSSL_SOURCE_DIR}/include ${OpenSSL_BINARY_DIR}/include CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_CRYPTO_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_CRYPTO_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_CRYPTO_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_SSL_LIBRARY ${OPENSSL_${OPENSSL_LIBRARY_TYPE}_SSL_LIBRARY} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_SSL_LIBRARIES ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_LIBRARIES ${OPENSSL_CRYPTO_LIBRARY} ${OPENSSL_SSL_LIBRARY} ${OPENSSL_DEPENDENCIES} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
set(OPENSSL_VERSION ${OPENSSL_CONFIGURED_VERSION} CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
-set(OPENSSL_APPLINK_SOURCE ${openssl_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
+set(OPENSSL_APPLINK_SOURCE ${OpenSSL_SOURCE_DIR}/ms/applink.c CACHE STRING "Override FindOpenSSL variables" FORCE)
|
||||
|
||||
add_library(OpenSSL::Crypto ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
|
||||
add_library(OpenSSL::SSL ${OPENSSL_LIBRARY_TYPE} IMPORTED GLOBAL)
|
||||
@@ -308,8 +303,8 @@ if(ANDROID)
|
||||
endif()
|
||||
|
||||
file(GLOB_RECURSE OPENSSL_SOURCES
|
||||
- ${openssl_SOURCE_DIR}/*.[ch]
|
||||
- ${openssl_SOURCE_DIR}/*.[ch].in
|
||||
+ ${OpenSSL_SOURCE_DIR}/*.[ch]
|
||||
+ ${OpenSSL_SOURCE_DIR}/*.[ch].in
|
||||
)
|
||||
|
||||
set(OPENSSL_BUILD_OUTPUT
|
||||
@@ -322,7 +317,7 @@ add_custom_command(
|
||||
OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||
COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||
DEPENDS ${OPENSSL_SOURCES}
|
||||
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
|
||||
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||
VERBATIM
|
||||
)
|
||||
|
||||
@@ -341,7 +336,7 @@ if(OPENSSL_TEST AND NOT CMAKE_CROSSCOMPILING)
|
||||
add_test(
|
||||
NAME openssl-test
|
||||
COMMAND ${OPENSSL_BUILD_TOOL} test VERBOSE_FAILURE=yes HARNESS_JOBS=${NUMBER_OF_THREADS}
|
||||
- WORKING_DIRECTORY ${openssl_BINARY_DIR}
|
||||
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||
)
|
||||
endif()
|
||||
|
||||
@@ -356,7 +351,7 @@ if(OPENSSL_INSTALL)
|
||||
install(CODE
|
||||
"execute_process(
|
||||
COMMAND ${OPENSSL_INSTALL_COMMAND}
|
||||
- WORKING_DIRECTORY \"${openssl_BINARY_DIR}\"
|
||||
+ WORKING_DIRECTORY \"${OpenSSL_BINARY_DIR}\"
|
||||
)"
|
||||
)
|
||||
endif()
|
||||
diff --git a/cmake/FetchOpenSSL.cmake b/cmake/FetchOpenSSL.cmake
|
||||
deleted file mode 100644
|
||||
index a43505d..0000000
|
||||
--- a/cmake/FetchOpenSSL.cmake
|
||||
+++ /dev/null
|
||||
@@ -1,64 +0,0 @@
|
||||
-function(fetch_openssl)
|
||||
- if(EXISTS "${OPENSSL_SOURCE}" AND IS_DIRECTORY "${OPENSSL_SOURCE}")
|
||||
- # Fetch the local OpenSSL source
|
||||
- if(NOT IS_ABSOLUTE "${OPENSSL_SOURCE}")
|
||||
- string(PREPEND OPENSSL_SOURCE ${CMAKE_SOURCE_DIR}/)
|
||||
- endif()
|
||||
-
|
||||
- string(REPLACE "\\" "/" openssl-source_SOURCE_DIR "${OPENSSL_SOURCE}")
|
||||
- set(openssl-source_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}/openssl-source-build)
|
||||
- else()
|
||||
- set(CPM_OPTIONS
|
||||
- NAME openssl-source
|
||||
- DOWNLOAD_ONLY ON
|
||||
- )
|
||||
-
|
||||
- if(NOT OPENSSL_CONFIGURE_VERBOSE)
|
||||
- list(APPEND CPM_OPTIONS QUIET)
|
||||
- endif()
|
||||
-
|
||||
- if("${OPENSSL_SOURCE}" MATCHES "^http")
|
||||
- # Download OpenSSL source from the internet
|
||||
- list(APPEND CPM_OPTIONS URL ${OPENSSL_SOURCE})
|
||||
- else()
|
||||
- # Download OpenSSL source from the official website
|
||||
- if("${OPENSSL_TARGET_VERSION}" STREQUAL "")
|
||||
- set(OPENSSL_TARGET_VERSION ${PROJECT_VERSION})
|
||||
- endif()
|
||||
-
|
||||
- if(OPENSSL_TARGET_VERSION VERSION_EQUAL PROJECT_VERSION)
|
||||
- list(APPEND CPM_OPTIONS URL_HASH SHA256=aaf51a1fe064384f811daeaeb4ec4dce7340ec8bd893027eee676af31e83a04f)
|
||||
- endif()
|
||||
-
|
||||
- if(OPENSSL_TARGET_VERSION MATCHES "^1\.1\.1[a-w]$")
|
||||
- string(REPLACE "." "_" OPENSSL_TAGGED_VERSION ${OPENSSL_TARGET_VERSION})
|
||||
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/OpenSSL_${OPENSSL_TAGGED_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
|
||||
- else()
|
||||
- list(APPEND CPM_OPTIONS URL https://github.com/openssl/openssl/releases/download/openssl-${OPENSSL_TARGET_VERSION}/openssl-${OPENSSL_TARGET_VERSION}.tar.gz)
|
||||
- endif()
|
||||
- endif()
|
||||
-
|
||||
- CPMAddPackage(${CPM_OPTIONS})
|
||||
- endif()
|
||||
-
|
||||
- # Clean build directory if source directory has changed
|
||||
- if(DEFINED CACHE{openssl-source_SOURCE_DIR_OLD} AND NOT openssl-source_SOURCE_DIR STREQUAL openssl-source_SOURCE_DIR_OLD)
|
||||
- set(openssl-source_SOURCE_DIR_OLD ${openssl-source_SOURCE_DIR} CACHE INTERNAL "Previously fetched OpenSSL source")
|
||||
-
|
||||
- if(IS_DIRECTORY ${openssl-source_BINARY_DIR})
|
||||
- file(REMOVE_RECURSE ${openssl-source_BINARY_DIR})
|
||||
- file(MAKE_DIRECTORY ${openssl-source_BINARY_DIR})
|
||||
- endif()
|
||||
- endif()
|
||||
-
|
||||
- # Override the FindOpenSSL module
|
||||
- FetchContent_Declare(
|
||||
- OpenSSL
|
||||
- SOURCE_DIR ${openssl-source_SOURCE_DIR}
|
||||
- BINARY_DIR ${openssl-source_BINARY_DIR}
|
||||
- OVERRIDE_FIND_PACKAGE
|
||||
- )
|
||||
- FetchContent_MakeAvailable(OpenSSL)
|
||||
-
|
||||
- return(PROPAGATE openssl_SOURCE_DIR openssl_BINARY_DIR)
|
||||
-endfunction()
|
||||
diff --git a/cmake/GetCPM.cmake b/cmake/GetCPM.cmake
|
||||
deleted file mode 100644
|
||||
index bfc50f5..0000000
|
||||
--- a/cmake/GetCPM.cmake
|
||||
+++ /dev/null
|
||||
@@ -1,5 +0,0 @@
|
||||
-file(
|
||||
- DOWNLOAD https://github.com/cpm-cmake/CPM.cmake/releases/latest/download/get_cpm.cmake
|
||||
- ${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake
|
||||
-)
|
||||
-include(${CMAKE_CURRENT_BINARY_DIR}/get_cpm.cmake)
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
From d46675fbb61eb6d51e478023ce4075e545ad4cfd Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sat, 30 May 2026 21:11:55 -0400
|
||||
Subject: [PATCH] use ccache
|
||||
|
||||
---
|
||||
CMakeLists.txt | 1 -
|
||||
cmake/ConfigureOpenSSL.cmake | 12 +++---------
|
||||
2 files changed, 3 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||
index 9ffd5a0..9ff14c8 100644
|
||||
--- a/CMakeLists.txt
|
||||
+++ b/CMakeLists.txt
|
||||
@@ -28,7 +28,6 @@ option(OPENSSL_ENABLE_PARALLEL "Build and test in parallel if possible" ON)
|
||||
option(OPENSSL_INSTALL "Install OpenSSL components to the <prefix> directory" OFF)
|
||||
option(OPENSSL_INSTALL_CERT "Install cert.pem to the <openssldir> directory" OFF)
|
||||
option(OPENSSL_TEST "Enable testing and build OpenSSL self tests" OFF)
|
||||
-option(OPENSSL_USE_CCACHE "Use ccache if available" ON)
|
||||
|
||||
if("${OPENSSL_BUILD_TARGET}" STREQUAL "")
|
||||
# Makefile target for build
|
||||
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
|
||||
index 211c18b..3d8cbed 100644
|
||||
--- a/cmake/ConfigureOpenSSL.cmake
|
||||
+++ b/cmake/ConfigureOpenSSL.cmake
|
||||
@@ -69,15 +69,9 @@ function(apply_ccache FILE)
|
||||
message(FATAL_ERROR "Couldn't find Makefile")
|
||||
endif()
|
||||
|
||||
- if(OPENSSL_USE_CCACHE)
|
||||
- find_program(CCACHE ccache)
|
||||
-
|
||||
- if(NOT CCACHE)
|
||||
- return()
|
||||
- endif()
|
||||
-
|
||||
+ if(USE_CCACHE)
|
||||
file(READ ${FILE} MAKEFILE)
|
||||
- string(REPLACE "\nCC=" "\nCC=ccache " MAKEFILE "${MAKEFILE}")
|
||||
+ string(REPLACE "\nCC=" "\nCC=${CCACHE_BINARY} " MAKEFILE "${MAKEFILE}")
|
||||
|
||||
if(MSVC)
|
||||
string(REPLACE "/Zi /Fdossl_static.pdb " "" MAKEFILE "${MAKEFILE}")
|
||||
@@ -171,4 +165,4 @@ function(configure_openssl)
|
||||
string(REPLACE "/W3" "/W0" MAKEFILE "${MAKEFILE}")
|
||||
file(WRITE ${OPENSSL_MAKEFILE} "${MAKEFILE}")
|
||||
endif()
|
||||
-endfunction()
|
||||
\ No newline at end of file
|
||||
+endfunction()
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
From 4a3cc92a7abad403529ed1cb4255ca63d9252de4 Mon Sep 17 00:00:00 2001
|
||||
From: crueter <crueter@eden-emu.dev>
|
||||
Date: Sat, 30 May 2026 21:48:42 -0400
|
||||
Subject: [PATCH 2/2] use cmake compiler flags
|
||||
|
||||
---
|
||||
cmake/ConfigureOpenSSL.cmake | 5 ++++-
|
||||
1 file changed, 4 insertions(+), 1 deletion(-)
|
||||
|
||||
diff --git a/cmake/ConfigureOpenSSL.cmake b/cmake/ConfigureOpenSSL.cmake
|
||||
index 3d8cbed..3012e05 100644
|
||||
--- a/cmake/ConfigureOpenSSL.cmake
|
||||
+++ b/cmake/ConfigureOpenSSL.cmake
|
||||
@@ -135,7 +135,10 @@ function(configure_openssl)
|
||||
endif()
|
||||
|
||||
execute_process(
|
||||
- COMMAND ${CONFIGURE_COMMAND}
|
||||
+ COMMAND ${CMAKE_COMMAND} -E env
|
||||
+ "CFLAGS=${CMAKE_C_FLAGS}"
|
||||
+ "CXXFLAGS=${CMAKE_CXX_FLAGS}"
|
||||
+ ${CONFIGURE_COMMAND}
|
||||
WORKING_DIRECTORY ${CONFIGURE_BUILD_DIR}
|
||||
${VERBOSE_OPTION}
|
||||
COMMAND_ERROR_IS_FATAL ANY
|
||||
--
|
||||
2.54.0
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
--- a/CMakeLists.txt 2026-06-01 23:53:16.498043856 -0400
|
||||
+++ b/CMakeLists.txt 2026-06-01 23:53:23.910543615 -0400
|
||||
@@ -312,13 +312,29 @@
|
||||
${OPENSSL_SHARED_CRYPTO_LIBRARY}
|
||||
${OPENSSL_SHARED_SSL_LIBRARY}
|
||||
)
|
||||
-add_custom_command(
|
||||
- OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||
- COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||
- DEPENDS ${OPENSSL_SOURCES}
|
||||
- WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||
- VERBATIM
|
||||
-)
|
||||
+if (WIN32)
|
||||
+ add_custom_command(
|
||||
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||
+ COMMAND ${OPENSSL_BUILD_COMMAND}
|
||||
+ DEPENDS ${OPENSSL_SOURCES}
|
||||
+ WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}
|
||||
+ VERBATIM)
|
||||
+else()
|
||||
+ set(_openssl_build_script "${CMAKE_CURRENT_BINARY_DIR}/BuildOpenSSL.cmake")
|
||||
+ file(WRITE ${_openssl_build_script}
|
||||
+ "execute_process(\n"
|
||||
+ " COMMAND ${OPENSSL_BUILD_COMMAND}\n"
|
||||
+ " WORKING_DIRECTORY ${OpenSSL_BINARY_DIR}\n"
|
||||
+ " RESULT_VARIABLE _r)\n"
|
||||
+ "if(_r)\n"
|
||||
+ " message(FATAL_ERROR \"OpenSSL build failed: \${_r}\")\n"
|
||||
+ "endif()\n")
|
||||
+ add_custom_command(
|
||||
+ OUTPUT ${OPENSSL_BUILD_OUTPUT}
|
||||
+ COMMAND ${CMAKE_COMMAND} -P ${_openssl_build_script}
|
||||
+ DEPENDS ${OPENSSL_SOURCES}
|
||||
+ VERBATIM)
|
||||
+endif()
|
||||
|
||||
if(PROJECT_IS_TOP_LEVEL)
|
||||
add_custom_target(openssl-build ALL DEPENDS ${OPENSSL_BUILD_OUTPUT})
|
||||
File diff suppressed because it is too large
Load Diff
+7
-17
@@ -1,7 +1,7 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
cmake_minimum_required(VERSION 3.31)
|
||||
cmake_minimum_required(VERSION 3.22)
|
||||
|
||||
project(yuzu)
|
||||
|
||||
@@ -10,7 +10,6 @@ list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/externals/cmake-modul
|
||||
|
||||
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm)
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
set(CMAKE_CXX_SCAN_FOR_MODULES 0)
|
||||
|
||||
include(DetectPlatform)
|
||||
include(DetectArchitecture)
|
||||
@@ -307,7 +306,7 @@ if (YUZU_ROOM)
|
||||
add_compile_definitions(YUZU_ROOM)
|
||||
endif()
|
||||
|
||||
if (UNIX AND NOT (PLATFORM_LINUX OR WIN32))
|
||||
if ((ANDROID OR APPLE OR UNIX) AND (NOT PLATFORM_LINUX OR ANDROID) AND NOT WIN32)
|
||||
if(CXX_APPLE OR CXX_CLANG)
|
||||
# libc++ has stop_token and jthread as experimental
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fexperimental-library")
|
||||
@@ -384,20 +383,13 @@ find_package(RenderDoc MODULE)
|
||||
# openssl funniness
|
||||
if (YUZU_USE_BUNDLED_OPENSSL)
|
||||
set(BUILD_SHARED_LIBS OFF)
|
||||
AddJsonPackage(openssl-ci)
|
||||
else()
|
||||
AddJsonPackage(openssl)
|
||||
set(OPENSSL_BUILD_VERBOSE ON)
|
||||
set(OPENSSL_CONFIGURE_VERBOSE ON)
|
||||
|
||||
if (OpenSSL_ADDED)
|
||||
AddJsonPackage(openssl-cmake)
|
||||
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (OpenSSL_ADDED)
|
||||
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
|
||||
endif()
|
||||
find_package(OpenSSL 3 REQUIRED)
|
||||
|
||||
message(STATUS "Fetching needed dependencies with CPM")
|
||||
|
||||
@@ -513,7 +505,7 @@ endfunction()
|
||||
# =============================================
|
||||
|
||||
if (APPLE)
|
||||
foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia Security UniformTypeIdentifiers)
|
||||
foreach(fw Carbon Metal Cocoa IOKit CoreVideo CoreMedia Security)
|
||||
find_library(${fw}_LIBRARY ${fw} REQUIRED)
|
||||
list(APPEND PLATFORM_LIBRARIES ${${fw}_LIBRARY})
|
||||
endforeach()
|
||||
@@ -525,8 +517,6 @@ elseif (WIN32)
|
||||
# PSAPI is the Process Status API
|
||||
set(PLATFORM_LIBRARIES ${PLATFORM_LIBRARIES} psapi imm32 version crypt32 rpcrt4 gdi32 wldap32 mswsock)
|
||||
endif()
|
||||
elseif (PLATFORM_MANAGARM)
|
||||
set(PLATFORM_LIBRARIES iconv intl)
|
||||
elseif (PLATFORM_HAIKU)
|
||||
# Haiku is so special :)
|
||||
set(PLATFORM_LIBRARIES bsd /boot/system/lib/libnetwork.so)
|
||||
@@ -590,9 +580,9 @@ if (ENABLE_QT)
|
||||
if (YUZU_USE_BUNDLED_QT)
|
||||
# Qt 6.8+ is broken on macOS (??)
|
||||
if (APPLE)
|
||||
AddQt(Eden-CI/Qt 6.7.3)
|
||||
AddQt(6.7.3)
|
||||
else()
|
||||
AddQt(Eden-CI/Qt 6.11.1)
|
||||
AddQt(6.9.3)
|
||||
endif()
|
||||
else()
|
||||
message(STATUS "Using system Qt")
|
||||
|
||||
+29
-51
@@ -3,7 +3,7 @@
|
||||
|
||||
set(CPM_SOURCE_CACHE "${PROJECT_SOURCE_DIR}/.cache/cpm" CACHE STRING "" FORCE)
|
||||
|
||||
if(MSVC OR ANDROID OR IOS)
|
||||
if(MSVC OR ANDROID)
|
||||
set(BUNDLED_DEFAULT ON)
|
||||
else()
|
||||
set(BUNDLED_DEFAULT OFF)
|
||||
@@ -128,8 +128,7 @@ function(AddDependentPackages)
|
||||
message(FATAL_ERROR "Partial dependency installation detected "
|
||||
"for the following packages:\n${package_names}\n"
|
||||
"You can solve this in one of two ways:\n"
|
||||
"1. Install or upgrade the following packages "
|
||||
"to your system if available:"
|
||||
"1. Install the following packages to your system if available:"
|
||||
"\n\t${bundled_names}\n"
|
||||
"2. Set the following variables to ON:"
|
||||
"\n\t${system_names}\n"
|
||||
@@ -248,9 +247,7 @@ function(AddJsonPackage)
|
||||
|
||||
set(multiValueArgs OPTIONS)
|
||||
|
||||
set(optionArgs MODULE)
|
||||
|
||||
cmake_parse_arguments(JSON "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}"
|
||||
cmake_parse_arguments(JSON "" "${oneValueArgs}" "${multiValueArgs}"
|
||||
"${ARGN}")
|
||||
|
||||
list(LENGTH ARGN argnLength)
|
||||
@@ -279,10 +276,6 @@ function(AddJsonPackage)
|
||||
|
||||
parse_object(${object})
|
||||
|
||||
if (JSON_MODULE)
|
||||
set(EXTRA_ARGS MODULE)
|
||||
endif()
|
||||
|
||||
if(ci)
|
||||
AddCIPackage(
|
||||
VERSION ${version}
|
||||
@@ -291,8 +284,8 @@ function(AddJsonPackage)
|
||||
PACKAGE ${package}
|
||||
EXTENSION ${extension}
|
||||
MIN_VERSION ${min_version}
|
||||
DISABLED_PLATFORMS ${disabled_platforms}
|
||||
${EXTRA_ARGS})
|
||||
DISABLED_PLATFORMS ${disabled_platforms})
|
||||
|
||||
else()
|
||||
if (NOT DEFINED JSON_FORCE_BUNDLED_PACKAGE)
|
||||
set(JSON_FORCE_BUNDLED_PACKAGE OFF)
|
||||
@@ -314,24 +307,23 @@ function(AddJsonPackage)
|
||||
FORCE_BUNDLED_PACKAGE "${JSON_FORCE_BUNDLED_PACKAGE}"
|
||||
SOURCE_SUBDIR "${source_subdir}"
|
||||
|
||||
GIT_VERSION "${git_version}"
|
||||
GIT_HOST "${git_host}"
|
||||
GIT_VERSION ${git_version}
|
||||
GIT_HOST ${git_host}
|
||||
|
||||
ARTIFACT "${artifact}"
|
||||
TAG "${tag}"
|
||||
${EXTRA_ARGS})
|
||||
ARTIFACT ${artifact}
|
||||
TAG ${tag})
|
||||
endif()
|
||||
|
||||
# pass stuff to parent scope
|
||||
Propagate(${package}_ADDED)
|
||||
Propagate(${package}_SOURCE_DIR)
|
||||
Propagate(${package}_BINARY_DIR)
|
||||
Propagate(CMAKE_PREFIX_PATH)
|
||||
endfunction()
|
||||
|
||||
function(AddPackage)
|
||||
cpm_set_policies()
|
||||
set(EXTRA_ARGS "")
|
||||
|
||||
# TODO(crueter): git clone?
|
||||
|
||||
#[[
|
||||
URL configurations, descending order of precedence:
|
||||
@@ -376,9 +368,7 @@ function(AddPackage)
|
||||
|
||||
set(multiValueArgs OPTIONS PATCHES)
|
||||
|
||||
set(optionArgs MODULE)
|
||||
|
||||
cmake_parse_arguments(PKG_ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}"
|
||||
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}"
|
||||
"${ARGN}")
|
||||
|
||||
if(NOT DEFINED PKG_ARGS_NAME)
|
||||
@@ -562,12 +552,6 @@ function(AddPackage)
|
||||
VERSION ${PKG_ARGS_VERSION})
|
||||
endif()
|
||||
|
||||
if (PKG_ARGS_MODULE)
|
||||
set(PKG_ARGS_DOWNLOAD_ONLY ON)
|
||||
elseif (NOT DEFINED PKG_ARGS_DOWNLOAD_ONLY)
|
||||
set(PKG_ARGS_DOWNLOAD_ONLY OFF)
|
||||
endif()
|
||||
|
||||
CPMAddPackage(
|
||||
NAME ${PKG_ARGS_NAME}
|
||||
URL ${pkg_url}
|
||||
@@ -617,14 +601,13 @@ function(AddPackage)
|
||||
endif()
|
||||
|
||||
# pass stuff to parent scope
|
||||
Propagate(${PKG_ARGS_NAME}_ADDED)
|
||||
Propagate(${PKG_ARGS_NAME}_SOURCE_DIR)
|
||||
Propagate(${PKG_ARGS_NAME}_BINARY_DIR)
|
||||
set(${PKG_ARGS_NAME}_ADDED "${${PKG_ARGS_NAME}_ADDED}"
|
||||
PARENT_SCOPE)
|
||||
set(${PKG_ARGS_NAME}_SOURCE_DIR "${${PKG_ARGS_NAME}_SOURCE_DIR}"
|
||||
PARENT_SCOPE)
|
||||
set(${PKG_ARGS_NAME}_BINARY_DIR "${${PKG_ARGS_NAME}_BINARY_DIR}"
|
||||
PARENT_SCOPE)
|
||||
|
||||
if (PKG_ARGS_MODULE)
|
||||
list(PREPEND CMAKE_PREFIX_PATH "${${ARTIFACT_PACKAGE}_SOURCE_DIR}")
|
||||
Propagate(CMAKE_PREFIX_PATH)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# TODO(crueter): we could do an AddMultiArchPackage, multiplatformpackage?
|
||||
@@ -707,20 +690,14 @@ function(AddCIPackage)
|
||||
set(pkgname linux-amd64)
|
||||
elseif(PLATFORM_LINUX AND ARCHITECTURE_arm64)
|
||||
set(pkgname linux-aarch64)
|
||||
elseif(APPLE AND NOT IOS)
|
||||
elseif(APPLE)
|
||||
set(pkgname macos-universal)
|
||||
elseif(IOS AND ARCHITECTURE_arm64)
|
||||
set(pkgname ios-aarch64)
|
||||
endif()
|
||||
|
||||
if (DEFINED pkgname AND NOT "${pkgname}" IN_LIST DISABLED_PLATFORMS)
|
||||
set(ARTIFACT
|
||||
"${ARTIFACT_NAME}-${pkgname}-${ARTIFACT_VERSION}.${ARTIFACT_EXT}")
|
||||
|
||||
if (PKG_ARGS_MODULE)
|
||||
set(EXTRA_ARGS MODULE)
|
||||
endif()
|
||||
|
||||
AddPackage(
|
||||
NAME ${ARTIFACT_PACKAGE}
|
||||
REPO ${ARTIFACT_REPO}
|
||||
@@ -731,22 +708,23 @@ function(AddCIPackage)
|
||||
KEY "${pkgname}-${ARTIFACT_VERSION}"
|
||||
HASH_SUFFIX sha512sum
|
||||
FORCE_BUNDLED_PACKAGE ON
|
||||
${EXTRA_ARGS})
|
||||
DOWNLOAD_ONLY ${PKG_ARGS_MODULE})
|
||||
|
||||
set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE)
|
||||
Propagate(${ARTIFACT_PACKAGE}_SOURCE_DIR)
|
||||
Propagate(CMAKE_PREFIX_PATH)
|
||||
set(${ARTIFACT_PACKAGE}_SOURCE_DIR
|
||||
"${${ARTIFACT_PACKAGE}_SOURCE_DIR}" PARENT_SCOPE)
|
||||
|
||||
if (PKG_ARGS_MODULE)
|
||||
list(PREPEND CMAKE_PREFIX_PATH "${${ARTIFACT_PACKAGE}_SOURCE_DIR}")
|
||||
Propagate(CMAKE_PREFIX_PATH)
|
||||
endif()
|
||||
else()
|
||||
find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED)
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# Utility function for Qt
|
||||
function(AddQt repo version)
|
||||
if (NOT DEFINED repo)
|
||||
message(FATAL_ERROR "[CPMUtil] AddQt: repo is required")
|
||||
endif()
|
||||
|
||||
function(AddQt version)
|
||||
if (NOT DEFINED version)
|
||||
message(FATAL_ERROR "[CPMUtil] AddQt: version is required")
|
||||
endif()
|
||||
@@ -756,7 +734,7 @@ function(AddQt repo version)
|
||||
PACKAGE Qt6
|
||||
VERSION ${version}
|
||||
MIN_VERSION 6
|
||||
REPO ${repo}
|
||||
REPO crueter-ci/Qt
|
||||
DISABLED_PLATFORMS
|
||||
android-x86_64 android-aarch64
|
||||
freebsd-amd64 solaris-amd64 openbsd-amd64
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
# SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
# SPDX-FileCopyrightText: 2023 Alexandre Bouvier <contact@amb.tf>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-or-later
|
||||
@@ -16,8 +13,7 @@ endif()
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(LLVM HANDLE_COMPONENTS CONFIG_MODE)
|
||||
|
||||
# Demangle only for Windows targets
|
||||
if (WIN32 AND LLVM_FOUND AND LLVM_Demangle_FOUND AND NOT TARGET LLVM::Demangle)
|
||||
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})
|
||||
|
||||
+2
-30
@@ -1,40 +1,12 @@
|
||||
{
|
||||
"openssl-ci": {
|
||||
"openssl": {
|
||||
"ci": true,
|
||||
"package": "OpenSSL",
|
||||
"name": "openssl",
|
||||
"repo": "crueter-ci/OpenSSL",
|
||||
"version": "4.0.0-11b7b6ea3b",
|
||||
"version": "3.6.0-1cb0d36b39",
|
||||
"min_version": "3"
|
||||
},
|
||||
"openssl-cmake": {
|
||||
"repo": "jimmy-park/openssl-cmake",
|
||||
"hash": "2cc185c924fd70e7d886257ca0caa42b3b8f7f712f2052b4f94dde74759e27022de76178460e18c9bdfc57c366583999e198fbb6052d4e7d91c099d15a0ca63e",
|
||||
"git_version": "3.6.2",
|
||||
"tag": "%VERSION%",
|
||||
"bundled": true,
|
||||
"options": [
|
||||
"OPENSSL_CONFIGURE_OPTIONS threads"
|
||||
],
|
||||
"patches": [
|
||||
"0001-cpmutil-compat.patch",
|
||||
"0002-use-ccache.patch",
|
||||
"0003-use-cmake-compiler-flags.patch",
|
||||
"0004-use-shell-wrapper.patch"
|
||||
]
|
||||
},
|
||||
"openssl": {
|
||||
"repo": "openssl/openssl",
|
||||
"package": "OpenSSL",
|
||||
"min_version": "3",
|
||||
"version": "3",
|
||||
"hash": "29002ce50cb95a4f4f1d0e9d3f684401fbd4eac34203dc2eef3b6334af5d44aa46bf788b63a6f5c139c383eafb7269ae87a58a9a3ad5912903b9773e545ccc0a",
|
||||
"git_version": "3.6.2",
|
||||
"tag": "openssl-%VERSION%",
|
||||
"patches": [
|
||||
"0001-add-bundled-cert.patch"
|
||||
]
|
||||
},
|
||||
"boost": {
|
||||
"package": "Boost",
|
||||
"repo": "boostorg/boost",
|
||||
|
||||
Vendored
+470
-504
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+443
-476
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+1337
-1490
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+477
-511
File diff suppressed because it is too large
Load Diff
Vendored
+474
-507
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
Vendored
+443
-476
File diff suppressed because it is too large
Load Diff
Vendored
+443
-476
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
Vendored
+443
-476
File diff suppressed because it is too large
Load Diff
Vendored
+488
-535
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
Vendored
+446
-480
File diff suppressed because it is too large
Load Diff
Vendored
+443
-476
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
Vendored
+476
-509
File diff suppressed because it is too large
Load Diff
Vendored
+470
-504
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+475
-508
File diff suppressed because it is too large
Load Diff
Vendored
+450
-486
File diff suppressed because it is too large
Load Diff
Vendored
+444
-477
File diff suppressed because it is too large
Load Diff
@@ -136,16 +136,6 @@ cmake -S . -B build -G "<GENERATOR>" -DCMAKE_C_COMPILER=clang-cl -DCMAKE_CXX_COM
|
||||
<img src="https://user-images.githubusercontent.com/42481638/216899275-d514ec6a-e563-470e-81e2-3e04f0429b68.png" width="500">
|
||||
</details>
|
||||
|
||||
#### Option D: Visual Studio with clang-cl
|
||||
|
||||
<details>
|
||||
1. Install `"x64 Native Tools Command Prompt"` for VS from the installer and also install `cmake-gui`.
|
||||
2. Open `"x64 Native Tools Command Prompt"` and type `cmake-gui`.
|
||||
3. Click configure choose ninja generator > specify native compilers.
|
||||
4. Put `"C:/Program Files/Microsoft Visual Studio/18/Community/VC/Tools/Llvm/x64/bin/clang-cl.exe"` as your C/C++ compiler path.
|
||||
5. Open `Visual studio > Open project` or Solution > Change to search for the CMake project file (`CMakeList.txt`) file on the cloned directory, and then build.
|
||||
</details>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
If your initial configure failed:
|
||||
|
||||
@@ -18,4 +18,3 @@
|
||||
- `linux-amd64`
|
||||
- `linux-aarch64`
|
||||
- `macos-universal`
|
||||
- `ios-aarch64`
|
||||
|
||||
@@ -61,8 +61,7 @@ In order: OpenSSL CI, Boost (tag + artifact), Opus (options + find_args), discor
|
||||
"version": "3.6.0",
|
||||
"min_version": "1.1.1",
|
||||
"disabled_platforms": [
|
||||
"macos-universal",
|
||||
"ios-aarch64"
|
||||
"macos-universal"
|
||||
]
|
||||
},
|
||||
"boost": {
|
||||
|
||||
+25
-2
@@ -69,6 +69,29 @@ Expressions can be `variable_names` or `1234` (numbers) or `*var` (dereference o
|
||||
|
||||
For more information type `info gdb` and read [the man page](https://man7.org/linux/man-pages/man1/gdb.1.html).
|
||||
|
||||
# RenderDoc (Graphic Debugging Tool)
|
||||
## Simple checklist for debugging black screens using Renderdoc
|
||||
|
||||
Guidelines for graphical debugging using RenderDoc: **[RenderDoc usage](./RenderDoc.md)**
|
||||
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it at [renderdoc.org](https://renderdoc.org).
|
||||
|
||||
Before using renderdoc to diagnose issues, it is always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, renderdoc can help debug validation errors if you do have them.
|
||||
|
||||
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
|
||||
Here is a short checklist of items to look at to make sure are appropriate:
|
||||
|
||||
- Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
|
||||
- Vertex buffers are bound
|
||||
- vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
|
||||
- Any bound push constants and descriptors have the right data - including:
|
||||
- Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
|
||||
- Pipeline state is correct
|
||||
- viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
|
||||
- Fill mode matches expected - usually solid
|
||||
- Culling mode makes sense - commonly back or none
|
||||
- The winding direction is correct - typically CCW (counter clockwise)
|
||||
- Scissor region is correct - usually same as viewport's x,y,width, &height
|
||||
- Blend state is correct
|
||||
- Depth state is correct - typically enabled with Function set to Less than or Equal
|
||||
- Swapchain images are bound when rendering to the swapchain
|
||||
- Image being rendered to is the same as the one being presented when rendering to the swapchain
|
||||
|
||||
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@ To build Eden, you MUST have a C++ compiler.
|
||||
|
||||
The following additional tools are also required:
|
||||
|
||||
* **[CMake](https://www.cmake.org/)** 3.31+ - already included with the Android SDK
|
||||
* **[CMake](https://www.cmake.org/)** 3.22+ - already included with the Android SDK
|
||||
* **[Git](https://git-scm.com/)** for version control
|
||||
* **[Windows installer](https://gitforwindows.org)**
|
||||
* **[Python3](https://www.python.org/downloads/)** 3.10+ - necessary to download external repositories
|
||||
|
||||
+2
-2
@@ -1,6 +1,6 @@
|
||||
# HOS Kernel
|
||||
|
||||
In brief, the HOS kernel is a microkernel, all services and programs run in userspace, the primary way to do communication between these is via `HIPC` (not covered here); otherwise most of the primitives reside in the forms of syscalls invoked via `svc #imm`. The kernel supports both 32-bit and 64-bit programs, and has the capacity to use 32, 36 and 39 bits of address space for spawned processes. Most of the networking stack is based off FreeBSD's network stack.
|
||||
In brief, the HOS kernel is a microkernel, some services and programs run in userspace, the primary way to do communication between these is via `HIPC` (not covered here); otherwise most of the primitives reside in the forms of syscalls invoked via `svc #imm`. The kernel supports both 32-bit and 64-bit programs, and has the capacity to use 32, 36 and 39 bits of address space for spawned processes. Most of the networking stack is based off FreeBSD's network stack.
|
||||
|
||||
The emulator implements the majority of the syscalls pertaining to the HOS kernel itself. When we talk about the HOS Kernel (in the context of the emulator) we are strictly speaking about the mechanisms from which syscalls are handled (and it's subsequent side effects, such as the page table book-keeping). The emulator at it's current state is unable to load a custom low-level kernel and do supervisor-level emulation.
|
||||
|
||||
@@ -28,4 +28,4 @@ Every process keeps it's own tracking of the following structures:
|
||||
|
||||
The emulator willingly restricts itself to only use 4 threads (to emulate 4 cores), this is because most existing applications do not benefit greatly from the added core count, and in fact can be detrimental due to extra contention. This translates equitatively to about 4 `ArmInterface` slots for each process, these are then redirected to whatever is the last `pc` of the last thread running on the core is meant to be; proceed to run it, then when returning (due to halt or interruption), proceed to reschedule the thread.
|
||||
|
||||
The scheduler as-is isn't 100% faithful to the original (for example the original is cooperative and not preemptive), and has great timing variance (especially due to the fact the emulator can run in systems with wildly different timings).
|
||||
The scheduler as-is isn't 100% faithful to the original, and has great timing variance (especially due to the fact the emulator can run in systems with wildly different timings).
|
||||
|
||||
@@ -12,7 +12,6 @@ This contains documentation created by developers. This contains build instructi
|
||||
- **[Development Guidelines](./Development.md)**
|
||||
- **[Dependencies](./Deps.md)**
|
||||
- **[Debug Guidelines](./Debug.md)**
|
||||
- **[RenderDoc usage](./RenderDoc.md)**
|
||||
- **[CPM - CMake Package Manager](./CPMUtil)**
|
||||
- **[Platform-Specific Caveats](./Caveats.md)**
|
||||
- **[The NVIDIA SM86 (Maxwell) GPU](./NvidiaGpu.md)**
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
# RenderDoc
|
||||
|
||||
Renderdoc is a free, cross platform, multi-graphics API debugger. It is an invaluable tool for diagnosing issues with graphics applications, and includes support for Vulkan. Get it at [renderdoc.org](https://renderdoc.org).
|
||||
|
||||
RenderDoc can capture Eden's Vulkan output when its Vulkan layer is loaded before Eden creates the Vulkan device. Before using renderdoc to diagnose issues, it is always good to make sure there are no validation errors. Any errors means the behavior of the application is undefined. That said, renderdoc can help debug validation errors if you do have them.
|
||||
|
||||
## Usage on Windows
|
||||
|
||||
You can either use RenderDoc UI to launch eden, or you can make eden attach it internally:
|
||||
|
||||
On Windows PowerShell:
|
||||
```powershell
|
||||
$env:ENABLE_VULKAN_RENDERDOC_CAPTURE='1'
|
||||
.\eden.exe
|
||||
```
|
||||
When RenderDoc is attached, Eden logs the default Windows capture folder:
|
||||
```text
|
||||
%LOCALAPPDATA%\Temp\RenderDoc
|
||||
```
|
||||
|
||||
Press RenderDoc's capture hotkey, usually `F12`, to capture a frame. To stop using RenderDoc, close Eden and launch it again without `ENABLE_VULKAN_RENDERDOC_CAPTURE`.
|
||||
|
||||
## Eden Hotkey
|
||||
|
||||
Eden also has a separate `Toggle Renderdoc Capture` hotkey behind the debug setting `renderdoc_hotkey`.
|
||||
That hotkey does not load or unload RenderDoc. It only toggles Eden's own manual capture through RenderDoc's API:
|
||||
|
||||
- first press: starts a capture
|
||||
- second press: ends that capture
|
||||
|
||||
## Simple checklist for debugging black screens using Renderdoc
|
||||
|
||||
When debugging a black screen, there are many ways the application could have setup Vulkan wrong.
|
||||
Here is a short checklist of items to look at to make sure are appropriate:
|
||||
|
||||
- Draw call counts are correct (aka not zero, or if rendering many triangles, not 3)
|
||||
- Vertex buffers are bound
|
||||
- vertex attributes are correct - Make sure the size & offset of each attribute matches what should it should be
|
||||
- Any bound push constants and descriptors have the right data - including:
|
||||
- Matrices have correct values - double check the model, view, & projection matrices are uploaded correctly
|
||||
- Pipeline state is correct
|
||||
- viewport range is correct - x,y are 0,0; width & height are screen dimensions, minDepth is 0, maxDepth is 1, NDCDepthRange is 0,1
|
||||
- Fill mode matches expected - usually solid
|
||||
- Culling mode makes sense - commonly back or none
|
||||
- The winding direction is correct - typically CCW (counter clockwise)
|
||||
- Scissor region is correct - usually same as viewport's x,y,width, &height
|
||||
- Blend state is correct
|
||||
- Depth state is correct - typically enabled with Function set to Less than or Equal
|
||||
- Swapchain images are bound when rendering to the swapchain
|
||||
- Image being rendered to is the same as the one being presented when rendering to the swapchain
|
||||
|
||||
Alternatively, a [RenderDoc Extension](https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw) ([Archive](https://web.archive.org/web/20250000000000*/https://github.com/baldurk/renderdoc-contrib/tree/main/baldurk/whereismydraw)) exists which automates doing a lot of these manual steps.
|
||||
@@ -30,6 +30,7 @@ Before touching the settings, please see the game boots with stock options. We t
|
||||
|
||||
## CPU
|
||||
|
||||
- `CPU/Virtual table bouncing`: Some games have the tendency to crash on loading due to an indirect bad jump (Pokemon ZA being the worst offender); this option lies to the game and tells it to just pretend it never executed a given function. This is fine for most casual users, but developers of switch applications **must** disable this. This temporary "hack" should hopefully be gone in 6-7 months from now on.
|
||||
- `Fastmem`, aka. `CPU/Enable Host MMU`: Enables "fastmem"; a detailed description of fastmem can be found [here](../dynarmic/Design.md#fast-memory-fastmem).
|
||||
- `CPU/Unsafe FMA`: Enables deliberate innacurate FMA behaviour which may affect how FMA returns any given operation - this may introduce tiny floating point errors which can cascade in sensitive code (i.e FFmpeg).
|
||||
- `CPU/Faster FRSQRTE and FRECPE`: Introduces accuracy errors on square root and reciprocals in exchange for less checks - this introduces inaccuracies with some cases but it's mostly safe.
|
||||
|
||||
Vendored
+2
-7
@@ -49,8 +49,8 @@ if (NOT TARGET stb::headers)
|
||||
add_library(stb::headers ALIAS stb)
|
||||
endif()
|
||||
|
||||
# ItaniumDemangle (Windows only)
|
||||
if (WIN32 AND NOT TARGET LLVM::Demangle)
|
||||
# ItaniumDemangle
|
||||
if (NOT TARGET LLVM::Demangle)
|
||||
add_library(demangle demangle/ItaniumDemangle.cpp)
|
||||
target_include_directories(demangle PUBLIC ./demangle)
|
||||
if (NOT MSVC)
|
||||
@@ -82,11 +82,6 @@ if (ARCHITECTURE_riscv64)
|
||||
AddJsonPackage(biscuit)
|
||||
endif()
|
||||
|
||||
# Lagoon
|
||||
if (ARCHITECTURE_loongarch64)
|
||||
AddJsonPackage(lagoon)
|
||||
endif()
|
||||
|
||||
# Vulkan stuff
|
||||
AddDependentPackages(vulkan-headers vulkan-utility-libraries)
|
||||
|
||||
|
||||
Vendored
+6
-11
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"sirit": {
|
||||
"repo": "eden-emulator/sirit",
|
||||
"git_version": "1.0.5",
|
||||
"git_version": "1.0.4",
|
||||
"tag": "v%VERSION%",
|
||||
"artifact": "sirit-source-%VERSION%.tar.zst",
|
||||
"hash_suffix": "sha512sum",
|
||||
@@ -23,16 +23,17 @@
|
||||
"package": "sirit",
|
||||
"name": "sirit",
|
||||
"repo": "eden-emulator/sirit",
|
||||
"version": "1.0.5"
|
||||
"version": "1.0.4"
|
||||
},
|
||||
"httplib": {
|
||||
"repo": "yhirose/cpp-httplib",
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "159ed94965018f2a371d45a3bfc1961e5fb1549e501ded70a6b4532d7fe99d0579c18b5195aff6e35f96f399b426cea2650ec9fb75ef80d4c9edeccb51f2e6c9",
|
||||
"git_version": "0.46.0",
|
||||
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
|
||||
"git_version": "0.37.0",
|
||||
"find_args": "MODULE GLOBAL",
|
||||
"patches": [
|
||||
"0001-mingw.patch"
|
||||
"0001-mingw.patch",
|
||||
"0002-fix-zstd.patch"
|
||||
],
|
||||
"options": [
|
||||
"HTTPLIB_REQUIRE_OPENSSL ON",
|
||||
@@ -66,12 +67,6 @@
|
||||
"tag": "v%VERSION%",
|
||||
"hash": "9697e80a7d5d9bcb3ce51051a9a24962fb90ca79d215f1f03ae6b58da8ba13a63b5dda1b4dde3d26ac6445029696b8ef2883f4e5a777b342bba01283ed293856"
|
||||
},
|
||||
"lagoon": {
|
||||
"repo": "loongson-community/lagoon",
|
||||
"tag": "%VERSION%",
|
||||
"version": "1.0.0",
|
||||
"hash": "b9380f99c6effaeccc6d8f81d4942e852c11ad28613df637e155451556ae5826f93765bee57a5c87a9740d2bd1db463ad0f55a947772fe9d57eeabae3efa373e"
|
||||
},
|
||||
"libadrenotools": {
|
||||
"repo": "eden-emulator/libadrenotools",
|
||||
"sha": "8ba23b42d7",
|
||||
|
||||
Vendored
+2
-2
@@ -59,7 +59,7 @@ endif()
|
||||
if (PLATFORM_PS4 OR PLATFORM_MANAGARM)
|
||||
# Doesn't support VA-API, don't go thru the embarrassment of trying to enable it
|
||||
list(APPEND FFmpeg_HWACCEL_FLAGS --disable-vaapi)
|
||||
elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING AND NOT ANDROID)
|
||||
elseif (UNIX AND NOT DEFINED FFmpeg_IS_CROSS_COMPILING)
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(LIBVA libva)
|
||||
pkg_check_modules(CUDA cuda)
|
||||
@@ -169,7 +169,7 @@ if (PLATFORM_PS4)
|
||||
)
|
||||
elseif (PLATFORM_MANAGARM)
|
||||
# Required for proper stuff
|
||||
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
|
||||
list(APPEND FFmpeg_CROSS_COMPILE_FLAGS
|
||||
--disable-pthreads
|
||||
--extra-libs="${FFmpeg_CROSS_COMPILE_LIBS}"
|
||||
)
|
||||
|
||||
+1
-22
@@ -8,7 +8,7 @@
|
||||
include_directories(.)
|
||||
|
||||
# Dynarmic
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64) AND NOT YUZU_STATIC_ROOM)
|
||||
if ((ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64) AND NOT YUZU_STATIC_ROOM)
|
||||
add_subdirectory(dynarmic)
|
||||
add_library(dynarmic::dynarmic ALIAS dynarmic)
|
||||
endif()
|
||||
@@ -21,41 +21,20 @@ if (YUZU_STATIC_BUILD)
|
||||
add_compile_definitions(QT_STATICPLUGIN)
|
||||
endif()
|
||||
|
||||
# Build identifiers
|
||||
if (NIGHTLY_BUILD)
|
||||
add_compile_definitions(NIGHTLY_BUILD)
|
||||
endif()
|
||||
|
||||
# Legacy (android only)
|
||||
if (YUZU_LEGACY)
|
||||
message(WARNING "Making legacy build. Performance may suffer.")
|
||||
add_compile_definitions(YUZU_LEGACY)
|
||||
endif()
|
||||
|
||||
# Genshin Spoof (android only)
|
||||
if (GENSHIN_SPOOF)
|
||||
message(WARNING "Making Genshin spoof build")
|
||||
add_compile_definitions(GENSHIN_SPOOF)
|
||||
endif()
|
||||
|
||||
# Build ID (mingw only right now)
|
||||
# Pretty much just refers to the CI "target" for this build
|
||||
if (NOT BUILD_ID)
|
||||
if (ARCHITECTURE_x86_64)
|
||||
set(BUILD_ID amd64)
|
||||
elseif(ARCHITECTURE_arm64)
|
||||
if (WIN32)
|
||||
set(BUILD_ID arm64)
|
||||
else()
|
||||
set(BUILD_ID aarch64)
|
||||
endif()
|
||||
else()
|
||||
set(BUILD_ID "${ARCHITECTURE}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_compile_definitions(BUILD_ID="${BUILD_ID}")
|
||||
|
||||
# Set compilation flags
|
||||
if (MSVC AND NOT CXX_CLANG)
|
||||
set(CMAKE_CONFIGURATION_TYPES Debug Release CACHE STRING "" FORCE)
|
||||
|
||||
@@ -256,7 +256,7 @@ android {
|
||||
|
||||
externalNativeBuild {
|
||||
cmake {
|
||||
version = "3.31.6"
|
||||
version = "3.22.1"
|
||||
path = file("${edenDir}/CMakeLists.txt")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.Configuration
|
||||
import android.graphics.Rect
|
||||
import android.graphics.drawable.Icon
|
||||
@@ -100,6 +101,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||
private var romSwapGeneration = 0
|
||||
private var hasEmulationSession = processHasEmulationSession
|
||||
private val romSwapStopTimeoutRunnable = Runnable { onRomSwapStopTimeout() }
|
||||
private val pictureInPictureFailureActions: MutableSet<String> = mutableSetOf()
|
||||
|
||||
private fun onRomSwapStopTimeout() {
|
||||
if (!isWaitingForRomSwapStop) {
|
||||
@@ -268,12 +270,18 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||
}
|
||||
|
||||
override fun onUserLeaveHint() {
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.S) {
|
||||
if (BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && !isInPictureInPictureMode) {
|
||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S ||
|
||||
!isPictureInPictureSupported() ||
|
||||
!BooleanSetting.PICTURE_IN_PICTURE.getBoolean() ||
|
||||
isInPictureInPictureMode
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||
runPictureInPictureAction("enter picture-in-picture mode") {
|
||||
enterPictureInPictureMode(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -653,7 +661,29 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||
return this.apply { setActions(pictureInPictureActions) }
|
||||
}
|
||||
|
||||
private fun isPictureInPictureSupported() =
|
||||
Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
|
||||
packageManager.hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
|
||||
|
||||
private fun runPictureInPictureAction(actionName: String, action: () -> Unit) {
|
||||
try {
|
||||
action()
|
||||
} catch (e: IllegalStateException) {
|
||||
if (pictureInPictureFailureActions.add(actionName)) {
|
||||
Log.warning("[PiP] Failed to $actionName: ${e.message}")
|
||||
}
|
||||
} catch (e: UnsupportedOperationException) {
|
||||
if (pictureInPictureFailureActions.add(actionName)) {
|
||||
Log.warning("[PiP] Failed to $actionName: ${e.message}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun buildPictureInPictureParams() {
|
||||
if (!isPictureInPictureSupported()) {
|
||||
return
|
||||
}
|
||||
|
||||
val pictureInPictureParamsBuilder = PictureInPictureParams.Builder()
|
||||
.getPictureInPictureActionsBuilder().getPictureInPictureAspectBuilder()
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
||||
@@ -663,7 +693,9 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
|
||||
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
|
||||
)
|
||||
}
|
||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||
runPictureInPictureAction("set picture-in-picture params") {
|
||||
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
|
||||
}
|
||||
}
|
||||
|
||||
fun displayMultiplayerDialog() {
|
||||
|
||||
@@ -33,5 +33,3 @@ if (ENABLE_UPDATE_CHECKER)
|
||||
endif()
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES ${CPACK_PACKAGE_EXECUTABLES} yuzu-android)
|
||||
|
||||
target_link_options(yuzu-android PRIVATE "-Wl,-Bsymbolic")
|
||||
|
||||
@@ -462,8 +462,8 @@
|
||||
<string name="renderer_resolution">الدقة (الإرساء/محمول)</string>
|
||||
<string name="renderer_vsync">VSync وضع</string>
|
||||
<string name="renderer_scaling_filter">مرشح ملائم للنافذة</string>
|
||||
<string name="fsr_sharpness">حدة FSR/SGSR</string>
|
||||
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام مرشحات FSR أو SGSR</string>
|
||||
<string name="fsr_sharpness">حدة FSR</string>
|
||||
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
|
||||
<string name="renderer_anti_aliasing">طريقة مضاد التعرج</string>
|
||||
|
||||
|
||||
@@ -503,8 +503,6 @@
|
||||
<string name="fast_gpu_time_description">يُجبر هذا الخيار معظم الألعاب على العمل بأعلى دقة عرض أصلية. استخدم 256 للحصول على أقصى أداء و512 للحصول على أعلى جودة رسومات.</string>
|
||||
<string name="skip_cpu_inner_invalidation">تخطي إبطال صلاحية وحدة المعالجة المركزية الداخلية</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">يتخطى بعض عمليات إبطال ذاكرة التخزين المؤقتة من جانب وحدة المعالجة المركزية أثناء تحديثات الذاكرة، مما يقلل من استخدام وحدة المعالجة المركزية ويحسن أداءها. قد يتسبب ذلك في حدوث أعطال أو تعطل في بعض الألعاب.</string>
|
||||
<string name="antiflicker">مضاد الوميض</string>
|
||||
<string name="antiflicker_description">يُجبر هذا الوضع وظائف وحدة معالجة الرسومات على الانتظار حتى يتم إرسال العمل إليها. استخدمه مع وضع وحدة معالجة الرسومات السريع لتجنب الوميض مع تأثير أقل على الأداء.</string>
|
||||
<string name="fix_bloom_effects">إصلاح تأثيرات التوهج</string>
|
||||
<string name="fix_bloom_effects_description">يقلل من ضبابية التوهج في LA/EOW (Adreno A6XX - A7XX/ Turnip)، ويزيل التوهج في Burnout. تحذير: قد يسبب تشوهات رسومية في ألعاب أخرى.</string>
|
||||
<string name="emulate_bgr565">محاكاة BGR565</string>
|
||||
|
||||
@@ -329,6 +329,8 @@
|
||||
<string name="renderer_resolution">ڕوونی (دۆخی دەستی/دۆخی دۆک)</string>
|
||||
<string name="renderer_vsync">دۆخی VSync</string>
|
||||
<string name="renderer_scaling_filter">فلتەری گونجاندنی پەنجەرە</string>
|
||||
<string name="fsr_sharpness">تیژی FSR</string>
|
||||
<string name="fsr_sharpness_description">دیاریکردنی تیژی وێنە لە کاتی بەکارهێنانی FSR</string>
|
||||
<string name="renderer_anti_aliasing">شێوازی دژە-خاوڕۆیی</string>
|
||||
|
||||
|
||||
|
||||
@@ -439,6 +439,8 @@
|
||||
<string name="renderer_resolution">Rozlišení (Handheld/V doku)</string>
|
||||
<string name="renderer_vsync">Režim VSync</string>
|
||||
<string name="renderer_scaling_filter">Škálovací filtr</string>
|
||||
<string name="fsr_sharpness">Ostrost FSR</string>
|
||||
<string name="fsr_sharpness_description">Určuje jak ostře bude obraz vypadat při použití dynamického kontrastu FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Metoda anti-aliasingu</string>
|
||||
|
||||
|
||||
|
||||
@@ -439,6 +439,8 @@ Wird der Handheld-Modus verwendet, verringert es die Auflösung und erhöht die
|
||||
<string name="renderer_resolution">Auflösung (Handheld/Gedockt)</string>
|
||||
<string name="renderer_vsync">VSync-Modus</string>
|
||||
<string name="renderer_scaling_filter">Skalierungsfilter</string>
|
||||
<string name="fsr_sharpness">FSR-Schärfe</string>
|
||||
<string name="fsr_sharpness_description">Bestimmt die Schärfe bei FSR-Nutzung.</string>
|
||||
<string name="renderer_anti_aliasing">Kantenglättung</string>
|
||||
|
||||
|
||||
|
||||
@@ -376,7 +376,7 @@
|
||||
<string name="qlaunch_applet">Qlaunch</string>
|
||||
<string name="qlaunch_description">Iniciar aplicaciones desde la pantalla de inicio del sistema</string>
|
||||
<string name="applets">Lanzador de Applet</string>
|
||||
<string name="applets_description">Ejecutar applets del sistema usando el firmware instalado</string>
|
||||
<string name="applets_description">Ejecutar applets de sistema usando el firmware instalado</string>
|
||||
<string name="applets_error_firmware">El firmware no está instalado</string>
|
||||
<string name="applets_error_applet">Applet no disponible</string>
|
||||
<string name="applets_error_description"><![CDATA[Por favor, asegúrese de que su archivo <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-prodkeys-and-titlekeys\">prod.keys</a> y el <a href=\"https://yuzu-mirror.github.io/help/quickstart/#dumping-system-firmware\">firmware</a> están instalados e inténtelo de nuevo.]]></string>
|
||||
@@ -456,8 +456,8 @@
|
||||
<string name="renderer_resolution">Resolución (Portátil/Sobremesa)</string>
|
||||
<string name="renderer_vsync">Modo de sincronización vertical</string>
|
||||
<string name="renderer_scaling_filter">Filtro de adaptación de ventana</string>
|
||||
<string name="fsr_sharpness">Nitidez FSR/SGSR</string>
|
||||
<string name="fsr_sharpness_description">Determina el grado de nitidez de la imagen al usar filtros FSR o SGSR</string>
|
||||
<string name="fsr_sharpness">Nitidez FSR</string>
|
||||
<string name="fsr_sharpness_description">Ajusta la intensidad del filtro de enfoque al usar el contraste dinámico de FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Método de suavizado de bordes</string>
|
||||
|
||||
|
||||
@@ -497,8 +497,6 @@
|
||||
<string name="fast_gpu_time_description">Fuerza a la mayoría de los juegos a ejecutarse a su resolución nativa más alta. Usa 256 para un máximo rendimiento y 512 para una fidelidad gráfica óptima.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Omitir invalidación interna de la CPU</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Omite ciertas invalidaciones de caché de la CPU durante las actualizaciones de memoria, lo que reduce el uso de la CPU y mejora su rendimiento. Esto puede causar fallos o bloqueos en algunos juegos.</string>
|
||||
<string name="antiflicker">Antiparpadeo</string>
|
||||
<string name="antiflicker_description">Fuerza a las funciones de devolución de llamada de la GPU a esperar a que se envíen las tareas a la GPU.\nÚsalo con el modo de GPU rápida para evitar el parpadeo con un menor impacto en el rendimiento.</string>
|
||||
<string name="fix_bloom_effects">Arreglar los efectos de resplandor</string>
|
||||
<string name="fix_bloom_effects_description">Reduce el efecto de resplandor en LA/EOW (Adreno A6XX - A7XX/ Turnip), elimina el resplandor en Burnout. Advertencia: puede causar artefactos gráficos en otros juegos.</string>
|
||||
<string name="emulate_bgr565">Emular BGR565</string>
|
||||
@@ -805,7 +803,7 @@
|
||||
<string name="select_content_type">Tipo de contenido</string>
|
||||
<string name="updates_and_dlc">Actualizaciones y contenido descargable</string>
|
||||
<string name="mods_and_cheats">Mods y trucos</string>
|
||||
<string name="addon_notice">Aviso importante sobre los complementos</string>
|
||||
<string name="addon_notice">Aviso importante de complementos</string>
|
||||
<!-- \"cheats/" "romfs/" and \"exefs/ should not be translated -->
|
||||
<string name="addon_notice_description">Para instalar mods y trucos, debe seleccionar una carpeta que contenga los directorios cheats/, romfs/, o exefs/ . ¡No podemos confirmar si éstos serán compatibles con su juego, así que tenga cuidado!</string>
|
||||
<string name="invalid_directory">Directorio no válido</string>
|
||||
@@ -816,7 +814,7 @@
|
||||
<string name="content_install_notice">Aviso importante de contenido</string>
|
||||
<string name="content_install_notice_description">El contenido seleccionado no es de este juego.\n¿Instalar aun que\?</string>
|
||||
<string name="confirm_uninstall">Confirmar desinstalación</string>
|
||||
<string name="confirm_uninstall_description">¿Estás seguro de que quieres desinstalar este complemento\?</string>
|
||||
<string name="confirm_uninstall_description">¿Está seguro de que quiere desinstalar este complemento\?</string>
|
||||
<string name="verify_integrity">Verificar integridad</string>
|
||||
<string name="verifying">Verificando...</string>
|
||||
<string name="verify_success">¡La verificación de integridad ha sido un éxito!</string>
|
||||
@@ -1074,7 +1072,7 @@
|
||||
|
||||
<!-- Black backgrounds theme -->
|
||||
<string name="use_black_backgrounds">Fondos oscuros</string>
|
||||
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
|
||||
<string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
|
||||
|
||||
<!-- Buttons -->
|
||||
<string name="enable_folder_button">Carpeta</string>
|
||||
|
||||
@@ -454,6 +454,8 @@
|
||||
<string name="renderer_resolution">Résolution (Mode Portable/Mode TV)</string>
|
||||
<string name="renderer_vsync">Mode VSync</string>
|
||||
<string name="renderer_scaling_filter">Filtre de fenêtre adaptatif</string>
|
||||
<string name="fsr_sharpness">Netteté FSR</string>
|
||||
<string name="fsr_sharpness_description">Détermine à quel point l\'image sera affinée lors de l\'utilisation du contraste dynamique FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Méthode d\'anticrénelage</string>
|
||||
|
||||
|
||||
|
||||
@@ -359,6 +359,8 @@
|
||||
<string name="renderer_resolution">רזולוציה (מעוגן/נייד)</string>
|
||||
<string name="renderer_vsync">מצב VSync</string>
|
||||
<string name="renderer_scaling_filter">פילטר מתאם חלון</string>
|
||||
<string name="fsr_sharpness">חדות FSR</string>
|
||||
<string name="fsr_sharpness_description">קובע את מידת החדות בעת שימוש ב-FSR.</string>
|
||||
<string name="renderer_anti_aliasing">שיטת Anti-aliasing</string>
|
||||
|
||||
|
||||
|
||||
@@ -348,6 +348,8 @@
|
||||
<string name="renderer_resolution">Felbontás (Kézi/Dockolt)</string>
|
||||
<string name="renderer_vsync">VSync mód</string>
|
||||
<string name="renderer_scaling_filter">Ablakhoz alkalmazkodó szűrő</string>
|
||||
<string name="fsr_sharpness">FSR élesség</string>
|
||||
<string name="fsr_sharpness_description">Meghatározza, milyen éles lesz a kép az FSR dinamikus kontraszt használata közben.</string>
|
||||
<string name="renderer_anti_aliasing">Élsimítási módszer</string>
|
||||
|
||||
|
||||
|
||||
@@ -380,6 +380,8 @@
|
||||
<string name="renderer_resolution">Resolusi (Handheld/Docked)</string>
|
||||
<string name="renderer_vsync">Mode Sinkronisasi Vertikal</string>
|
||||
<string name="renderer_scaling_filter">Filter penyesuaian jendela</string>
|
||||
<string name="fsr_sharpness">Ketajaman FSR</string>
|
||||
<string name="fsr_sharpness_description">Menentukan seberapa tajam gambar akan terlihat saat menggunakan kontras dinamis FSR</string>
|
||||
<string name="renderer_anti_aliasing">Metode anti-aliasing</string>
|
||||
|
||||
|
||||
|
||||
@@ -387,6 +387,8 @@
|
||||
<string name="renderer_resolution">Risoluzione (Portatile/Docked)</string>
|
||||
<string name="renderer_vsync">Modalità VSync</string>
|
||||
<string name="renderer_scaling_filter">Filtro adattivo della finestra </string>
|
||||
<string name="fsr_sharpness">Nitidezza FSR</string>
|
||||
<string name="fsr_sharpness_description">Determina quanto sarà nitida l\'immagine utilizzando il contrasto dinamico di FSR</string>
|
||||
<string name="renderer_anti_aliasing">Metodo di anti-aliasing</string>
|
||||
|
||||
|
||||
|
||||
@@ -329,6 +329,8 @@
|
||||
<string name="renderer_resolution">Oppløsning (håndholdt/dokket)</string>
|
||||
<string name="renderer_vsync">VSync-modus</string>
|
||||
<string name="renderer_scaling_filter">Filter for vindustilpasning</string>
|
||||
<string name="fsr_sharpness">FSR-skarphet</string>
|
||||
<string name="fsr_sharpness_description">Bestemmer bildekvalitet med FSR</string>
|
||||
<string name="renderer_anti_aliasing">Anti-aliasing-metode</string>
|
||||
|
||||
|
||||
|
||||
@@ -439,6 +439,8 @@
|
||||
<string name="renderer_resolution">Rozdzielczość (Handheld/Zadokowany)</string>
|
||||
<string name="renderer_vsync">Synchronizacja pionowa VSync</string>
|
||||
<string name="renderer_scaling_filter">Filtr adaptacji rozdzielczości</string>
|
||||
<string name="fsr_sharpness">Ostrość FSR</string>
|
||||
<string name="fsr_sharpness_description">Kontroluje ostrość obrazu w FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Metoda wygładzania krawędzi</string>
|
||||
|
||||
|
||||
|
||||
@@ -430,6 +430,8 @@
|
||||
<string name="renderer_resolution">Resolução (Portátil/Modo TV)</string>
|
||||
<string name="renderer_vsync">Modo de VSync</string>
|
||||
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
|
||||
<string name="fsr_sharpness">Nitidez do FSR</string>
|
||||
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao utilizar o contraste dinâmico do FSR</string>
|
||||
<string name="renderer_anti_aliasing">Método de Anti-aliasing</string>
|
||||
|
||||
|
||||
|
||||
@@ -352,6 +352,8 @@
|
||||
<string name="renderer_resolution">Resolução (Portátil/Ancorado)</string>
|
||||
<string name="renderer_vsync">Modo VSync</string>
|
||||
<string name="renderer_scaling_filter">Filtro de Adaptação da Janela</string>
|
||||
<string name="fsr_sharpness">Nitidez do FSR</string>
|
||||
<string name="fsr_sharpness_description">Determina a nitidez da imagem ao usar contraste dinâmico do FSR</string>
|
||||
<string name="renderer_anti_aliasing">Método de Anti-Serrilhado</string>
|
||||
|
||||
|
||||
|
||||
@@ -458,8 +458,8 @@
|
||||
<string name="renderer_resolution">Разрешение (портативное/в док-станции)</string>
|
||||
<string name="renderer_vsync">Режим верт. синхронизации</string>
|
||||
<string name="renderer_scaling_filter">Фильтр адаптации окна</string>
|
||||
<string name="fsr_sharpness">Резкость FSR/SGSR</string>
|
||||
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR или SGSR фильтров</string>
|
||||
<string name="fsr_sharpness">Резкость FSR</string>
|
||||
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Метод сглаживания</string>
|
||||
|
||||
|
||||
@@ -499,8 +499,6 @@
|
||||
<string name="fast_gpu_time_description">Принудительно запускает большинство игр в их максимальном нативном разрешении. Используйте значение 256 для максимальной производительности и 512 для максимального качества графики.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Пропустить внутреннюю инвалидацию ЦП</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Пропускает некоторые инвалидации кэша на стороне ЦП при обновлениях памяти, уменьшая нагрузку на процессор и повышая производительность. Может вызывать сбои в некоторых играх.</string>
|
||||
<string name="antiflicker">Анти-мерцание</string>
|
||||
<string name="antiflicker_description">Принудительно заставляет обратные вызовы ГПУ-фильтра ожидать выполнения отправленных задач на ГПУ. Используйте с Быстрым режимом ГПУ, что бы избежать мерцаний с меньшим влиянием на производительность.</string>
|
||||
<string name="fix_bloom_effects">Исправить эффекты размытия</string>
|
||||
<string name="fix_bloom_effects_description">Частично убирает размытие в LA/EOW (Adreno A6XX - A7XX/ Turnip), полностью отключает его в Burnout. Внимание: может вызывать графические артефакты в других играх.</string>
|
||||
<string name="emulate_bgr565">Эмулировать BGR565</string>
|
||||
|
||||
@@ -351,6 +351,8 @@
|
||||
<string name="renderer_resolution">Резолуција (ручно / прикључено)</string>
|
||||
<string name="renderer_vsync">Всинц мод</string>
|
||||
<string name="renderer_scaling_filter">Филтер прилагођавања прозора</string>
|
||||
<string name="fsr_sharpness">ФСР оштрина</string>
|
||||
<string name="fsr_sharpness_description">Одређује колико ће се слика наоштрен трајати док користи \"ФСР\" динамички контраст</string>
|
||||
<string name="renderer_anti_aliasing">Метода против алиасирања</string>
|
||||
|
||||
|
||||
|
||||
@@ -458,8 +458,8 @@
|
||||
<string name="renderer_resolution">Роздільна здатність (Портативний/Док)</string>
|
||||
<string name="renderer_vsync">Режим верт. синхронізації</string>
|
||||
<string name="renderer_scaling_filter">Фільтр масштабування вікна</string>
|
||||
<string name="fsr_sharpness">Різкість FSR/SGSR</string>
|
||||
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні фільтрів FSR або SGSR.</string>
|
||||
<string name="fsr_sharpness">Різкість FSR</string>
|
||||
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні FSR.</string>
|
||||
<string name="renderer_anti_aliasing">Згладжування</string>
|
||||
|
||||
|
||||
@@ -499,8 +499,6 @@
|
||||
<string name="fast_gpu_time_description">Примушує більшість ігор працювати на їхній максимальній нативній роздільності. Використовуйте 256 для максимальної продуктивності та 512 для найкращої якості.</string>
|
||||
<string name="skip_cpu_inner_invalidation">Пропустити внутрішнє інвалідування CPU</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">Пропускає деякі інвалідації кешу на стороні CPU під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</string>
|
||||
<string name="antiflicker">Антимерехтіння</string>
|
||||
<string name="antiflicker_description">Змушує механізм синхронізації чекати, доки ГП завершить подані завдання. Використовуйте з режимом ГП «Швидко», щоб уникнути мерехтіння з меншими втратами продуктивності.</string>
|
||||
<string name="fix_bloom_effects">Виправити ефекти світіння</string>
|
||||
<string name="fix_bloom_effects_description">Зменшує розмиття світіння в LA/EOW (Adreno A6XX–A7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
|
||||
<string name="emulate_bgr565">Емулювати BGR565</string>
|
||||
|
||||
@@ -327,6 +327,8 @@
|
||||
<string name="renderer_resolution">Độ phân giải (Handheld/Docked)</string>
|
||||
<string name="renderer_vsync">Chế độ VSync</string>
|
||||
<string name="renderer_scaling_filter">Bộ lọc điều chỉnh cửa sổ</string>
|
||||
<string name="fsr_sharpness">Độ sắc nét FSR</string>
|
||||
<string name="fsr_sharpness_description">Độ sắc nét khi dùng FSR</string>
|
||||
<string name="renderer_anti_aliasing">Phương pháp khử răng cưa</string>
|
||||
|
||||
|
||||
|
||||
@@ -452,8 +452,8 @@
|
||||
<string name="renderer_resolution">分辨率 (掌机模式/主机模式)</string>
|
||||
<string name="renderer_vsync">垂直同步模式</string>
|
||||
<string name="renderer_scaling_filter">窗口滤镜</string>
|
||||
<string name="fsr_sharpness">FSR/SGSR 锐度</string>
|
||||
<string name="fsr_sharpness_description">确定在使用 FSR 或 SGSR 过滤器时的图像锐度</string>
|
||||
<string name="fsr_sharpness">FSR 锐化度</string>
|
||||
<string name="fsr_sharpness_description">确定使用 FSR 的动态对比度功能时的图像锐化程度</string>
|
||||
<string name="renderer_anti_aliasing">抗锯齿方式</string>
|
||||
|
||||
|
||||
@@ -493,10 +493,8 @@
|
||||
<string name="fast_gpu_time_description">强制大多数游戏以其最高原生分辨率运行。设置为 256 可获得最佳性能,设置为 512 可获得最佳画面保真度。</string>
|
||||
<string name="skip_cpu_inner_invalidation">跳过CPU内部无效化</string>
|
||||
<string name="skip_cpu_inner_invalidation_description">在内存更新期间跳过某些CPU端缓存无效化,减少CPU使用率并提高其性能。可能会导致某些游戏出现故障或崩溃。</string>
|
||||
<string name="antiflicker">防闪烁</string>
|
||||
<string name="antiflicker_description">强制 GPU 围栏回调等待已提交的 GPU 任务。配合“快速 GPU 模式”一起使用,以避免画面闪烁现象,仅会牺牲少量性能。</string>
|
||||
<string name="fix_bloom_effects">修复 Bloom 效果</string>
|
||||
<string name="fix_bloom_effects_description">减少《智慧的再现》和《众神的三角力量2》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
|
||||
<string name="fix_bloom_effects_description">减少《塞尔达传说:智慧的再现》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
|
||||
<string name="emulate_bgr565">模拟 BGR565</string>
|
||||
<string name="emulate_bgr565_description">修复游戏中的颜色反转或是异常的画面瑕疵或阴影问题</string>
|
||||
<string name="rescale_hack">启用旧版缩放处理</string>
|
||||
|
||||
@@ -437,6 +437,8 @@
|
||||
<string name="renderer_resolution">解析度 (手提/底座)</string>
|
||||
<string name="renderer_vsync">垂直同步</string>
|
||||
<string name="renderer_scaling_filter">視窗適應過濾器</string>
|
||||
<string name="fsr_sharpness">FSR 銳化度</string>
|
||||
<string name="fsr_sharpness_description">使用 FSR 時圖片的銳化程度</string>
|
||||
<string name="renderer_anti_aliasing">抗鋸齒</string>
|
||||
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||
@@ -177,8 +177,10 @@ void SinkStream::ProcessAudioOutAndRender(std::span<s16> output_buffer, std::siz
|
||||
queued_buffers.store(0);
|
||||
release_cv.notify_one();
|
||||
}
|
||||
|
||||
static constexpr std::array<s16, 6> silence{};
|
||||
for (size_t i = 0; i < num_frames; i++)
|
||||
std::memset(&output_buffer[i * frame_size], 0, frame_size_bytes);
|
||||
std::memcpy(&output_buffer[i * frame_size], silence.data(), frame_size_bytes);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -141,12 +141,12 @@ add_library(
|
||||
vector_math.h
|
||||
virtual_buffer.cpp
|
||||
virtual_buffer.h
|
||||
wall_clock.cpp
|
||||
wall_clock.h
|
||||
zstd_compression.cpp
|
||||
zstd_compression.h
|
||||
fs/ryujinx_compat.h fs/ryujinx_compat.cpp
|
||||
fs/symlink.h fs/symlink.cpp
|
||||
cpu_features.cpp
|
||||
cpu_features.h
|
||||
httplib.h
|
||||
net/net.h net/net.cpp)
|
||||
|
||||
@@ -180,7 +180,10 @@ endif()
|
||||
if(ARCHITECTURE_x86_64)
|
||||
target_sources(
|
||||
common
|
||||
PRIVATE
|
||||
PRIVATE x64/cpu_detect.cpp
|
||||
x64/cpu_detect.h
|
||||
x64/cpu_wait.cpp
|
||||
x64/cpu_wait.h
|
||||
x64/rdtsc.cpp
|
||||
x64/rdtsc.h
|
||||
x64/xbyak.h)
|
||||
@@ -231,11 +234,11 @@ if(CXX_CLANG)
|
||||
endif()
|
||||
|
||||
if (BOOST_NO_HEADERS)
|
||||
target_link_libraries(common PUBLIC Boost::algorithm Boost::heap Boost::icl Boost::pool)
|
||||
target_link_libraries(common PUBLIC Boost::algorithm Boost::icl Boost::pool)
|
||||
else()
|
||||
target_link_libraries(common PUBLIC Boost::headers)
|
||||
endif()
|
||||
target_link_libraries(common PRIVATE OpenSSL::SSL)
|
||||
|
||||
target_link_libraries(common PUBLIC Boost::filesystem Boost::context httplib::httplib nlohmann_json::nlohmann_json)
|
||||
|
||||
if (lz4_ADDED)
|
||||
@@ -243,12 +246,7 @@ if (lz4_ADDED)
|
||||
endif()
|
||||
|
||||
target_link_libraries(common PUBLIC fmt::fmt stb::headers Threads::Threads unordered_dense::unordered_dense)
|
||||
target_link_libraries(common PRIVATE lz4::lz4 zstd::zstd)
|
||||
|
||||
# Please refer to src/common/demangle.cpp
|
||||
if (WIN32)
|
||||
target_link_libraries(common PRIVATE LLVM::Demangle)
|
||||
endif()
|
||||
target_link_libraries(common PRIVATE lz4::lz4 LLVM::Demangle zstd::zstd)
|
||||
|
||||
if(ANDROID)
|
||||
# For ASharedMemory_create
|
||||
|
||||
@@ -1,12 +1,7 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2005-2014 Daniel James
|
||||
// SPDX-FileCopyrightText: 2016 Austin Appleby
|
||||
// SPDX-License-Identifier: BSL-1.0
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <climits>
|
||||
#include <cstdint>
|
||||
|
||||
+14
-28
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -6,44 +6,30 @@
|
||||
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#ifdef _WIN32
|
||||
#include <llvm/Demangle/Demangle.h>
|
||||
#else
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
#include "common/demangle.h"
|
||||
|
||||
static bool IsItanium(std::string_view name) {
|
||||
// A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
|
||||
auto const pos = name.find_first_not_of('_');
|
||||
return pos > 0 && pos <= 4 && pos < name.size() && name[pos] == 'Z';
|
||||
}
|
||||
#include "common/demangle.h"
|
||||
#include "common/scope_exit.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
std::string DemangleSymbol(const std::string& mangled) {
|
||||
if (mangled.size() > 0) {
|
||||
if (IsItanium(mangled)) {
|
||||
#ifdef _WIN32
|
||||
// requires the use of llvm
|
||||
auto const is_itanium = [](std::string_view name) -> bool {
|
||||
// A valid Itanium encoding requires 1-4 leading underscores, followed by 'Z'.
|
||||
auto const pos = name.find_first_not_of('_');
|
||||
return pos > 0 && pos <= 4 && pos < name.size() && name[pos] == 'Z';
|
||||
};
|
||||
std::string ret = mangled;
|
||||
if (is_itanium(mangled)) {
|
||||
if (char* p = llvm::itaniumDemangle(mangled); p != nullptr) {
|
||||
std::string ret = std::string{p};
|
||||
ret = std::string{p};
|
||||
std::free(p);
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
// can safely use libc++ and glibcxx provided demangling functions
|
||||
// it's available since 2008(!) so no system should have issues with it
|
||||
// see https://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-html-USERS-4.3/a01696.html
|
||||
int status;
|
||||
if (char* p = abi::__cxa_demangle(mangled.c_str(), NULL, NULL, &status); p != nullptr) {
|
||||
std::string ret = std::string{p};
|
||||
std::free(p);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return mangled;
|
||||
return ret;
|
||||
}
|
||||
return std::string{};
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
@@ -33,7 +30,7 @@ std::string NativeErrorToString(int e) {
|
||||
return ret;
|
||||
#else
|
||||
char err_str[255];
|
||||
#if defined(__ANDROID__) || \
|
||||
#if defined(ANDROID) || \
|
||||
(defined(__GLIBC__) && (_GNU_SOURCE || (_POSIX_C_SOURCE < 200112L && _XOPEN_SOURCE < 600)))
|
||||
// Thread safe (GNU-specific)
|
||||
const char* str = strerror_r(e, err_str, sizeof(err_str));
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
#include "common/fs/fs_android.h"
|
||||
#endif
|
||||
#include "common/logging.h"
|
||||
@@ -259,7 +259,7 @@ void IOFile::Open(const fs::path& path, FileAccessMode mode, FileType type, File
|
||||
} else {
|
||||
_wfopen_s(&file, path.c_str(), AccessModeToWStr(mode, type));
|
||||
}
|
||||
#elif __ANDROID__
|
||||
#elif ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
ASSERT_MSG(mode == FileAccessMode::Read, "Content URI file access is for read-only!");
|
||||
const auto fd = Android::OpenContentUri(path, Android::OpenMode::Read);
|
||||
@@ -396,7 +396,7 @@ u64 IOFile::GetSize() const {
|
||||
// Flush any unwritten buffered data into the file prior to retrieving the file size.
|
||||
std::fflush(file);
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#if ANDROID
|
||||
u64 file_size = 0;
|
||||
if (Android::IsContentUri(file_path)) {
|
||||
file_size = Android::GetSize(file_path);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
#include "common/fs/file.h"
|
||||
#include "common/fs/fs.h"
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
#include "common/fs/fs_android.h"
|
||||
#endif
|
||||
#include "common/fs/path_util.h"
|
||||
@@ -532,7 +532,7 @@ void IterateDirEntriesRecursively(const std::filesystem::path& path,
|
||||
|
||||
bool Exists(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
return Android::Exists(path);
|
||||
} else {
|
||||
@@ -545,7 +545,7 @@ bool Exists(const fs::path& path) {
|
||||
|
||||
bool IsFile(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
return !Android::IsDirectory(path);
|
||||
} else {
|
||||
@@ -558,7 +558,7 @@ bool IsFile(const fs::path& path) {
|
||||
|
||||
bool IsDir(const fs::path& path) {
|
||||
std::error_code ec;
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
return Android::IsDirectory(path);
|
||||
} else {
|
||||
@@ -611,7 +611,7 @@ fs::file_type GetEntryType(const fs::path& path) {
|
||||
}
|
||||
|
||||
u64 GetSize(const fs::path& path) {
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
return Android::GetSize(path);
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
#include "common/assert.h"
|
||||
#include "common/fs/fs.h"
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
#include "common/fs/fs_android.h"
|
||||
#endif
|
||||
#include "common/fs/fs_paths.h"
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
LEGACY_PATH(Yuzu, YUZU)
|
||||
LEGACY_PATH(Suyu, SUYU)
|
||||
#undef LEGACY_PATH
|
||||
#elif __ANDROID__
|
||||
#elif ANDROID
|
||||
ASSERT(!eden_path.empty());
|
||||
eden_path_cache = eden_path / CACHE_DIR;
|
||||
eden_path_config = eden_path / CONFIG_DIR;
|
||||
@@ -447,11 +447,11 @@ std::vector<std::string> SplitPathComponentsCopy(std::string_view filename) {
|
||||
|
||||
std::string SanitizePath(std::string_view path_, DirectorySeparator directory_separator) {
|
||||
std::string path(path_);
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (Android::IsContentUri(path)) {
|
||||
return path;
|
||||
}
|
||||
#endif // __ANDROID__
|
||||
#endif // ANDROID
|
||||
|
||||
char type1 = directory_separator == DirectorySeparator::BackwardSlash ? '/' : '\\';
|
||||
char type2 = directory_separator == DirectorySeparator::BackwardSlash ? '\\' : '/';
|
||||
@@ -482,7 +482,7 @@ std::string GetParentPath(std::string_view path) {
|
||||
return std::string(path);
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (path[0] != '/') {
|
||||
std::string path_string{path};
|
||||
return FS::Android::GetParentDirectory(path_string);
|
||||
|
||||
@@ -320,7 +320,7 @@ struct DebuggerBackend final : public Backend {
|
||||
void Flush() noexcept override {}
|
||||
};
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
/// @brief Backend that writes to the Android logcat
|
||||
struct LogcatBackend : public Backend {
|
||||
explicit LogcatBackend() noexcept = default;
|
||||
@@ -359,7 +359,7 @@ struct Impl {
|
||||
#ifdef _WIN32
|
||||
lambda(static_cast<Backend&>(debugger_backend));
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
lambda(static_cast<Backend&>(lc_backend));
|
||||
#endif
|
||||
}
|
||||
@@ -372,7 +372,7 @@ struct Impl {
|
||||
#ifdef _WIN32
|
||||
DebuggerBackend debugger_backend{};
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
LogcatBackend lc_backend{};
|
||||
#endif
|
||||
std::chrono::steady_clock::time_point time_origin{std::chrono::steady_clock::now()};
|
||||
|
||||
+10
-15
@@ -62,21 +62,16 @@ std::vector<Asset> Release::GetPlatformAssets() const {
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#ifdef _MSC_VER
|
||||
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip"});
|
||||
#else // _MSC_VER
|
||||
find_asset("Standard", {BUILD_ID "-gcc-standard.exe", BUILD_ID "-gcc-standard.zip"});
|
||||
find_asset("PGO", {BUILD_ID "-clang-pgo.exe", BUILD_ID "-clang-pgo.zip"});
|
||||
#endif // _MSC_VER
|
||||
find_asset("Standard", {"amd64-msvc-standard.exe", "amd64-msvc-standard.zip", "mingw-amd64-gcc-standard.exe", "mingw-amd64-gcc-standard.zip"});
|
||||
find_asset("PGO", {"mingw-amd64-clang-pgo.exe", "mingw-amd64-clang-pgo.zip"});
|
||||
#elif defined(ARCHITECTURE_arm64)
|
||||
find_asset("Standard", {"arm64-clang-standard.exe", "arm64-clang-standard.zip"});
|
||||
find_asset("PGO", {"arm64-clang-pgo.exe", "arm64-clang-pgo.zip"});
|
||||
#endif // ARCHITECTURE_arm64
|
||||
find_asset("Standard", {"mingw-arm64-clang-standard.exe", "mingw-arm64-clang-standard.zip"});
|
||||
find_asset("PGO", {"mingw-arm64-clang-pgo.exe", "mingw-arm64-clang-pgo.zip"});
|
||||
#endif
|
||||
#elif defined(__APPLE__)
|
||||
#ifdef ARCHITECTURE_arm64
|
||||
find_asset("Standard", {"standard.dmg", "standard.tar.gz", ".dmg", ".tar.gz"});
|
||||
find_asset("PGO", {"pgo.dmg", "pgo.tar.gz"});
|
||||
#endif // ARCHITECTURE_arm64
|
||||
find_asset("Standard", {".dmg", ".tar.gz"});
|
||||
#endif
|
||||
#elif defined(__ANDROID__)
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
find_asset("Standard", {"chromeos.apk"});
|
||||
@@ -87,9 +82,9 @@ std::vector<Asset> Release::GetPlatformAssets() const {
|
||||
find_asset("Standard", {"optimized.apk"});
|
||||
#else
|
||||
find_asset("Standard", {"standard.apk"});
|
||||
#endif // GENSHIN_SPOOF
|
||||
#endif // ARCHITECTURE_arm64
|
||||
#endif // __APPLE__
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return found_assets;
|
||||
}
|
||||
|
||||
|
||||
+10
-10
@@ -359,7 +359,7 @@ struct Values {
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<int, true> fsr_sharpening_slider{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
0,
|
||||
#else
|
||||
25,
|
||||
@@ -417,7 +417,7 @@ struct Values {
|
||||
linkage, 0, "bg_blue", Category::Renderer, Specialization::Default, true, true};
|
||||
|
||||
SwitchableSetting<GpuAccuracy, true> gpu_accuracy{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
GpuAccuracy::Low,
|
||||
#else
|
||||
GpuAccuracy::Medium,
|
||||
@@ -447,7 +447,7 @@ struct Values {
|
||||
"nvdec_emulation", Category::RendererAdvanced};
|
||||
|
||||
SwitchableSetting<AnisotropyMode, true> max_anisotropy{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
AnisotropyMode::Default,
|
||||
#else
|
||||
AnisotropyMode::Automatic,
|
||||
@@ -500,7 +500,7 @@ struct Values {
|
||||
Category::RendererAdvanced};
|
||||
|
||||
SwitchableSetting<bool> use_reactive_flushing{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
false,
|
||||
#else
|
||||
true,
|
||||
@@ -519,7 +519,7 @@ struct Values {
|
||||
true,
|
||||
true};
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
SwitchableSetting<bool> use_optimized_vertex_buffers{linkage,
|
||||
false,
|
||||
"use_optimized_vertex_buffers",
|
||||
@@ -553,7 +553,7 @@ struct Values {
|
||||
true,
|
||||
true};
|
||||
SwitchableSetting<bool> async_presentation{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
false,
|
||||
#else
|
||||
false,
|
||||
@@ -599,7 +599,7 @@ struct Values {
|
||||
Category::RendererHacks};
|
||||
|
||||
SwitchableSetting<ExtendedDynamicState> dyna_state{linkage,
|
||||
#if defined(__ANDROID__)
|
||||
#if defined(ANDROID)
|
||||
ExtendedDynamicState::Disabled,
|
||||
#elif defined(__APPLE__)
|
||||
ExtendedDynamicState::Disabled,
|
||||
@@ -618,7 +618,7 @@ struct Values {
|
||||
Specialization::Scalar};
|
||||
|
||||
SwitchableSetting<bool> vertex_input_dynamic_state{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#if defined (ANDROID)
|
||||
false,
|
||||
#else
|
||||
true,
|
||||
@@ -634,7 +634,7 @@ struct Values {
|
||||
linkage, false, "disable_shader_loop_safety_checks", Category::RendererDebug};
|
||||
Setting<bool> enable_renderdoc_hotkey{linkage, false, "renderdoc_hotkey",
|
||||
Category::RendererDebug};
|
||||
#if defined(__ANDROID__) && defined(ARCHITECTURE_arm64)
|
||||
#if defined(ANDROID) && defined(ARCHITECTURE_arm64)
|
||||
// Debug override for automatic BCn patching detection
|
||||
Setting<bool> patch_old_qcom_drivers{linkage, false, "patch_old_qcom_drivers",
|
||||
Category::RendererDebug};
|
||||
@@ -679,7 +679,7 @@ struct Values {
|
||||
Setting<s32> current_user{linkage, 0, "current_user", Category::System};
|
||||
|
||||
SwitchableSetting<ConsoleMode> use_docked_mode{linkage,
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
ConsoleMode::Handheld,
|
||||
#else
|
||||
ConsoleMode::Docked,
|
||||
|
||||
+18
-20
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
@@ -20,14 +20,10 @@
|
||||
namespace Common {
|
||||
|
||||
struct SlotId {
|
||||
static constexpr u32 TAGGED_MASK = 0x7fffffff;
|
||||
static constexpr u32 TAGGED_VALUE = 0x80000000;
|
||||
static constexpr u32 INVALID_INDEX = (std::numeric_limits<u32>::max)();
|
||||
|
||||
constexpr u32 Value() const noexcept {
|
||||
return index & (~TAGGED_VALUE);
|
||||
}
|
||||
constexpr auto operator<=>(const SlotId&) const noexcept = default;
|
||||
|
||||
constexpr explicit operator bool() const noexcept {
|
||||
return index != INVALID_INDEX;
|
||||
}
|
||||
@@ -51,12 +47,12 @@ public:
|
||||
Iterator& operator++() noexcept {
|
||||
const u64* const bitset = slot_vector->stored_bitset.data();
|
||||
const u32 size = static_cast<u32>(slot_vector->stored_bitset.size()) * 64;
|
||||
if (id.Value() < size) {
|
||||
if (id.index < size) {
|
||||
do {
|
||||
++id.index;
|
||||
} while (id.Value() < size && !IsValid(bitset));
|
||||
if (id.Value() == size) {
|
||||
id = SlotId{};
|
||||
} while (id.index < size && !IsValid(bitset));
|
||||
if (id.index == size) {
|
||||
id.index = SlotId::INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
@@ -89,7 +85,7 @@ public:
|
||||
: slot_vector{slot_vector_}, id{id_} {}
|
||||
|
||||
bool IsValid(const u64* bitset) const noexcept {
|
||||
return ((bitset[id.Value() / 64] >> (id.Value() % 64)) & 1) != 0;
|
||||
return ((bitset[id.index / 64] >> (id.index % 64)) & 1) != 0;
|
||||
}
|
||||
|
||||
SlotVector<T>* slot_vector;
|
||||
@@ -111,12 +107,12 @@ public:
|
||||
|
||||
[[nodiscard]] T& operator[](SlotId id) noexcept {
|
||||
ValidateIndex(id);
|
||||
return values[id.Value()].object;
|
||||
return values[id.index].object;
|
||||
}
|
||||
|
||||
[[nodiscard]] const T& operator[](SlotId id) const noexcept {
|
||||
ValidateIndex(id);
|
||||
return values[id.Value()].object;
|
||||
return values[id.index].object;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
@@ -129,9 +125,9 @@ public:
|
||||
}
|
||||
|
||||
void erase(SlotId id) noexcept {
|
||||
values[id.Value()].object.~T();
|
||||
free_list.push_back(id.Value());
|
||||
ResetStorageBit(id.Value());
|
||||
values[id.index].object.~T();
|
||||
free_list.push_back(id.index);
|
||||
ResetStorageBit(id.index);
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator begin() noexcept {
|
||||
@@ -145,7 +141,7 @@ public:
|
||||
}
|
||||
|
||||
[[nodiscard]] Iterator end() noexcept {
|
||||
return Iterator(this, SlotId{});
|
||||
return Iterator(this, SlotId{SlotId::INVALID_INDEX});
|
||||
}
|
||||
|
||||
[[nodiscard]] size_t size() const noexcept {
|
||||
@@ -179,8 +175,8 @@ private:
|
||||
|
||||
void ValidateIndex(SlotId id) const noexcept {
|
||||
DEBUG_ASSERT(id);
|
||||
DEBUG_ASSERT(id.Value() / 64 < stored_bitset.size());
|
||||
DEBUG_ASSERT(((stored_bitset[id.Value() / 64] >> (id.Value() % 64)) & 1) != 0);
|
||||
DEBUG_ASSERT(id.index / 64 < stored_bitset.size());
|
||||
DEBUG_ASSERT(((stored_bitset[id.index / 64] >> (id.index % 64)) & 1) != 0);
|
||||
}
|
||||
|
||||
[[nodiscard]] u32 FreeValueIndex() noexcept {
|
||||
@@ -212,7 +208,9 @@ private:
|
||||
|
||||
const size_t old_free_size = free_list.size();
|
||||
free_list.resize(old_free_size + (new_capacity - values_capacity));
|
||||
std::iota(free_list.begin() + old_free_size, free_list.end(), u32(values_capacity));
|
||||
std::iota(free_list.begin() + old_free_size, free_list.end(),
|
||||
static_cast<u32>(values_capacity));
|
||||
|
||||
delete[] values;
|
||||
values = new_values;
|
||||
values_capacity = new_capacity;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2013 Dolphin Emulator Project
|
||||
@@ -18,7 +18,7 @@
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
#include <common/fs/fs_android.h>
|
||||
#endif
|
||||
|
||||
@@ -45,7 +45,7 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _
|
||||
if (full_path.empty())
|
||||
return false;
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#ifdef ANDROID
|
||||
if (full_path[0] != '/') {
|
||||
*_pPath = Common::FS::Android::GetParentDirectory(full_path);
|
||||
*_pFilename = Common::FS::Android::GetFilename(full_path);
|
||||
|
||||
+4
-2
@@ -1,4 +1,4 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2012 PPSSPP Project
|
||||
@@ -10,10 +10,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <cstdlib>
|
||||
#endif
|
||||
#include <bit>
|
||||
#include <cstring>
|
||||
#include <type_traits>
|
||||
#include <bit>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
+2
-113
@@ -4,8 +4,6 @@
|
||||
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include <chrono>
|
||||
#include <limits>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
|
||||
@@ -20,35 +18,24 @@
|
||||
#elif defined(_WIN32)
|
||||
#include <windows.h>
|
||||
#include "common/string_util.h"
|
||||
#include "common/windows/timer_resolution.h"
|
||||
#else
|
||||
#if defined(__FreeBSD__)
|
||||
#include <sys/cpuset.h>
|
||||
#include <sys/_cpuset.h>
|
||||
#include <pthread_np.h>
|
||||
// Compatibility with CPUset
|
||||
#define cpu_set_t cpuset_t
|
||||
#elif defined(__DragonFly__) || defined(__OpenBSD__) || defined(__Bitrig__)
|
||||
#include <pthread_np.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "common/cpu_features.h"
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#else
|
||||
#include <x86intrin.h>
|
||||
#ifdef __FreeBSD__
|
||||
# define cpu_set_t cpuset_t
|
||||
#endif
|
||||
#include "common/x64/rdtsc.h"
|
||||
#endif
|
||||
#include "core/core_timing.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
@@ -157,102 +144,4 @@ void PinCurrentThreadToPerformanceCore(size_t core_id) {
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
// On Linux and UNIX systems, a futex would nominally be used to cover the costs
|
||||
// the idea is that it's intuitivelly cheaper to use a direct instruction as opposed to a full futex call
|
||||
// the underlying libc++ implementation uses pthread_cond_timedwait which MAY invoke a futex
|
||||
// Let's pretend the OS is too expensive to jump into, and avoid ANY context switches
|
||||
// this should *IN THEORY* lower CPU usage while just waiting for stuff effectively
|
||||
// For windows the minimal quanta resolution is about 500us, and normal CRT cond var is 1.5ms(?)
|
||||
// so may as well avoid that too
|
||||
// Let's just give ALL platforms the same mechanisms (almost) for when they have umonitor OR waitpkg
|
||||
#ifdef __clang__
|
||||
__attribute__((target("waitpkg,mwaitx")))
|
||||
#elif defined(__GNUC__)
|
||||
#pragma GCC target("waitpkg")
|
||||
#pragma GCC target("mwaitx")
|
||||
#endif
|
||||
bool Event::WaitFor(const std::chrono::nanoseconds time) {
|
||||
#ifdef _WIN32
|
||||
auto const start = Common::X64::FencedRDTSC();
|
||||
auto const& caps = Common::g_cpu_caps;
|
||||
[[maybe_unused]] auto const end = start + Common::g_wall_clock.NsToTicks(time);
|
||||
if (caps.monitorx) {
|
||||
while (true) {
|
||||
// Armed monitor, as per manual, MWAITX must be conditional if the condition isn't satisfied
|
||||
// to prevent a race condition.
|
||||
_mm_monitorx(reinterpret_cast<u64*>(std::addressof(is_set)), 0, 0);
|
||||
if (!is_set.load()) {
|
||||
// RDTSC may be fenced here due to atomic load
|
||||
#ifdef _MSC_VER
|
||||
auto const now = __rdtsc();
|
||||
#else
|
||||
auto const now = _rdtsc();
|
||||
#endif
|
||||
if (end > now) {
|
||||
u32 const cycles = std::min<u32>((std::numeric_limits<u32>::max)(), s64(end) - s64(now));
|
||||
// See here: https://github.com/torvalds/linux/blob/948a64995aca6820abefd17f1a4258f5835c5ad9/arch/x86/lib/delay.c#L93
|
||||
// MWAITX accepts a 32-bit input timer which determines the total number of cycles to wait for
|
||||
// NOT THE TOTAL ABSOLUTE TSC VALUE, it's just a delta
|
||||
// BIT[1] = use a timer
|
||||
// Hint = 0: Use C1 state when sleepy (means slower wakeup but better savings)
|
||||
_mm_mwaitx(1 << 1, 0u, cycles);
|
||||
if (!is_set.load())
|
||||
return false;
|
||||
} else
|
||||
return false; //timeout
|
||||
}
|
||||
bool expected = true;
|
||||
if (is_set.compare_exchange_weak(expected, false, std::memory_order_release))
|
||||
return true;
|
||||
}
|
||||
} else if (caps.waitpkg) {
|
||||
// #UD If CPUID.7.0:ECX.WAITPKG[bit 5]=0.
|
||||
while (true) {
|
||||
_umonitor(std::addressof(is_set));
|
||||
if (!is_set.load() && !_umwait(0, end)) //umwait is absolute time!!!
|
||||
return false;
|
||||
bool expected = true;
|
||||
if (is_set.compare_exchange_weak(expected, false, std::memory_order_release))
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
#ifdef _MSC_VER
|
||||
while (!is_set.load() && end > __rdtsc())
|
||||
Common::Windows::SleepForOneTick();
|
||||
#else
|
||||
while (!is_set.load() && end > _rdtsc())
|
||||
Common::Windows::SleepForOneTick();
|
||||
#endif
|
||||
if (is_set.load())
|
||||
Reset();
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
|
||||
return false;
|
||||
is_set = false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
bool Event::WaitFor(const std::chrono::nanoseconds time) {
|
||||
#ifdef _WIN32
|
||||
auto const end = Common::g_wall_clock.GetTimeNS() + time;
|
||||
while (!is_set.load() && end > Common::g_wall_clock.GetTimeNS())
|
||||
Common::Windows::SleepForOneTick();
|
||||
if (is_set.load())
|
||||
Reset();
|
||||
return true;
|
||||
#else
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
|
||||
return false;
|
||||
is_set = false;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace Common
|
||||
|
||||
+10
-4
@@ -34,10 +34,16 @@ public:
|
||||
is_set = false;
|
||||
}
|
||||
|
||||
bool WaitFor(const std::chrono::nanoseconds time);
|
||||
bool WaitFor(const std::chrono::nanoseconds& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_for(lk, time, [this] { return is_set.load(); }))
|
||||
return false;
|
||||
is_set = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
template<class Clock, class Duration>
|
||||
bool WaitUntil(const std::chrono::time_point<Clock, Duration> time) {
|
||||
template <class Clock, class Duration>
|
||||
bool WaitUntil(const std::chrono::time_point<Clock, Duration>& time) {
|
||||
std::unique_lock lk{mutex};
|
||||
if (!condvar.wait_until(lk, time, [this] { return is_set.load(); }))
|
||||
return false;
|
||||
@@ -57,9 +63,9 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
alignas(64) std::atomic<bool> is_set{false};
|
||||
std::condition_variable condvar;
|
||||
std::mutex mutex;
|
||||
std::atomic_bool is_set{false};
|
||||
};
|
||||
|
||||
class Barrier {
|
||||
|
||||
@@ -0,0 +1,197 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/steady_clock.h"
|
||||
#include "common/uint128.h"
|
||||
#include "common/wall_clock.h"
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "common/x64/cpu_detect.h"
|
||||
#include "common/x64/rdtsc.h"
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
|
||||
: invariant{invariant_}
|
||||
, rdtsc_frequency{rdtsc_frequency_}
|
||||
, ns_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_)}
|
||||
, us_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_)}
|
||||
, ms_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_)}
|
||||
, cntpct_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_)}
|
||||
, gputick_rdtsc_factor{invariant_ ? 0 : GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_)}
|
||||
{}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
if (invariant)
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
if (invariant)
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
if (invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
return s64(Common::X64::FencedRDTSC());
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
if (invariant)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#elif defined(HAS_NCE)
|
||||
namespace {
|
||||
|
||||
[[nodiscard]] WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
|
||||
return (WallClock::FactorType(num) << 64) / den;
|
||||
}
|
||||
|
||||
[[nodiscard]] u64 MultiplyHigh(u64 m, WallClock::FactorType factor) noexcept {
|
||||
return static_cast<u64>((m * factor) >> 64);
|
||||
}
|
||||
|
||||
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
|
||||
u64 cntfrq_el0 = 0;
|
||||
#ifdef ANDROID
|
||||
std::string_view board{""};
|
||||
char buffer[PROP_VALUE_MAX];
|
||||
int len{__system_property_get("ro.product.board", buffer)};
|
||||
board = std::string_view(buffer, static_cast<size_t>(len));
|
||||
if (board == "s5e9925") { // Exynos 2200
|
||||
cntfrq_el0 = 25600000;
|
||||
} else if (board == "exynos2100") { // Exynos 2100
|
||||
cntfrq_el0 = 26000000;
|
||||
} else if (board == "exynos9810") { // Exynos 9810
|
||||
cntfrq_el0 = 26000000;
|
||||
} else if (board == "s5e8825") { // Exynos 1280
|
||||
cntfrq_el0 = 26000000;
|
||||
} else {
|
||||
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
}
|
||||
return cntfrq_el0;
|
||||
#else
|
||||
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
return cntfrq_el0;
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
|
||||
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
|
||||
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
|
||||
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
|
||||
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
|
||||
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
|
||||
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
s64 cntvct_el0 = 0;
|
||||
asm volatile(
|
||||
"dsb ish\n\t"
|
||||
"mrs %[cntvct_el0], cntvct_el0\n\t"
|
||||
"dsb ish\n\t"
|
||||
: [cntvct_el0] "=r"(cntvct_el0)
|
||||
);
|
||||
return cntvct_el0;
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
WallClock CreateOptimalClock() noexcept {
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
auto const& caps = GetCPUCaps();
|
||||
return WallClock(!(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den), caps.tsc_frequency);
|
||||
#elif defined(HAS_NCE)
|
||||
return WallClock(false, 1);
|
||||
#else
|
||||
return WallClock(true, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace Common
|
||||
@@ -1,14 +1,11 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <ratio>
|
||||
@@ -46,9 +43,6 @@ public:
|
||||
/// @returns Whether the clock directly uses the host's hardware clock.
|
||||
bool IsNative() const;
|
||||
|
||||
// @returns Nanoseconds to native ticks
|
||||
u64 NsToTicks(std::chrono::nanoseconds ns) const;
|
||||
|
||||
static inline u64 NSToCNTPCT(u64 ns) {
|
||||
return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
}
|
||||
@@ -75,6 +69,7 @@ public:
|
||||
return cpu_tick * CPUTickToGPUTickRatio::num / CPUTickToGPUTickRatio::den;
|
||||
}
|
||||
|
||||
protected:
|
||||
using NsRatio = std::nano;
|
||||
using UsRatio = std::micro;
|
||||
using MsRatio = std::milli;
|
||||
@@ -92,96 +87,31 @@ public:
|
||||
using CPUTickToGPUTickRatio = std::ratio<GPUTickFreq, CPUTickFreq>;
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
bool invariant;
|
||||
u64 rdtsc_frequency;
|
||||
u64 ns_rdtsc_factor;
|
||||
u64 us_rdtsc_factor;
|
||||
u64 ms_rdtsc_factor;
|
||||
u64 rdtsc_ns_factor;
|
||||
u64 cntpct_rdtsc_factor;
|
||||
u64 gputick_rdtsc_factor;
|
||||
bool invariant;
|
||||
#elif defined(HAS_NCE)
|
||||
public:
|
||||
using FactorType = unsigned __int128;
|
||||
[[nodiscard]] inline FactorType GetGuestCNTFRQFactor() const {
|
||||
|
||||
FactorType GetGuestCNTFRQFactor() const {
|
||||
return guest_cntfrq_factor;
|
||||
}
|
||||
protected:
|
||||
FactorType ns_cntfrq_factor;
|
||||
FactorType us_cntfrq_factor;
|
||||
FactorType ms_cntfrq_factor;
|
||||
FactorType cntfrq_ns_factor;
|
||||
FactorType guest_cntfrq_factor;
|
||||
FactorType gputick_cntfrq_factor;
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
/// x86/x64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
enum class Manufacturer : u8 {
|
||||
Unknown = 0,
|
||||
Intel = 1,
|
||||
AMD = 2,
|
||||
Hygon = 3,
|
||||
};
|
||||
|
||||
static Manufacturer ParseManufacturer(std::string_view brand_string);
|
||||
|
||||
Manufacturer manufacturer;
|
||||
char brand_string[13];
|
||||
|
||||
char cpu_string[48];
|
||||
|
||||
u32 base_frequency;
|
||||
u32 max_frequency;
|
||||
u32 bus_frequency;
|
||||
|
||||
u32 tsc_crystal_ratio_denominator;
|
||||
u32 tsc_crystal_ratio_numerator;
|
||||
u32 crystal_frequency;
|
||||
u64 tsc_frequency; // Derived from the above three values
|
||||
|
||||
bool sse3 : 1;
|
||||
bool ssse3 : 1;
|
||||
bool sse4_1 : 1;
|
||||
bool sse4_2 : 1;
|
||||
|
||||
bool avx : 1;
|
||||
bool avx2 : 1;
|
||||
bool avx512f : 1;
|
||||
bool avx512dq : 1;
|
||||
bool avx512cd : 1;
|
||||
bool avx512bw : 1;
|
||||
bool avx512vl : 1;
|
||||
bool avx512vbmi : 1;
|
||||
bool avx512bitalg : 1;
|
||||
|
||||
bool aes : 1;
|
||||
bool bmi1 : 1;
|
||||
bool bmi2 : 1;
|
||||
bool f16c : 1;
|
||||
bool fma : 1;
|
||||
bool gfni : 1;
|
||||
bool invariant_tsc : 1;
|
||||
bool lzcnt : 1;
|
||||
bool monitorx : 1;
|
||||
bool movbe : 1;
|
||||
bool pclmulqdq : 1;
|
||||
bool popcnt : 1;
|
||||
bool sha : 1;
|
||||
bool waitpkg : 1;
|
||||
};
|
||||
#else
|
||||
struct CPUCaps {
|
||||
bool padding;
|
||||
};
|
||||
|
||||
#endif
|
||||
};
|
||||
|
||||
/// Detects CPU core count
|
||||
std::optional<int> GetProcessorCount();
|
||||
|
||||
/// @brief Global cpu caps
|
||||
extern const CPUCaps g_cpu_caps;
|
||||
/// @brief Global wall clock
|
||||
extern const WallClock g_wall_clock;
|
||||
[[nodiscard]] WallClock CreateOptimalClock() noexcept;
|
||||
|
||||
} // namespace Common
|
||||
@@ -10,32 +10,34 @@
|
||||
#include <fstream>
|
||||
#include <iterator>
|
||||
#include <optional>
|
||||
#include <algorithm>
|
||||
#include <string_view>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
#include <sys/types.h>
|
||||
#include <machine/cpufunc.h>
|
||||
#elif defined(__ANDROID__)
|
||||
#include <sys/system_properties.h>
|
||||
#endif
|
||||
|
||||
#include "common/steady_clock.h"
|
||||
#include "common/uint128.h"
|
||||
#include "common/bit_util.h"
|
||||
#include "common/common_types.h"
|
||||
#include "common/cpu_features.h"
|
||||
#include "common/logging.h"
|
||||
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
#include "common/x64/cpu_detect.h"
|
||||
#include "common/x64/rdtsc.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
static inline u64 xgetbv(u32 index) { return _xgetbv(index); }
|
||||
|
||||
static inline u64 xgetbv(u32 index) {
|
||||
return _xgetbv(index);
|
||||
}
|
||||
#else
|
||||
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
// clang-format off
|
||||
#include <sys/types.h>
|
||||
#include <machine/cpufunc.h>
|
||||
// clang-format on
|
||||
#endif
|
||||
|
||||
static inline void __cpuidex(int info[4], u32 function_id, u32 subfunction_id) {
|
||||
#if defined(__DragonFly__) || defined(__FreeBSD__)
|
||||
// Despite the name, this is just do_cpuid() with ECX as second input.
|
||||
@@ -48,7 +50,11 @@ static inline void __cpuidex(int info[4], u32 function_id, u32 subfunction_id) {
|
||||
: "a"(function_id), "c"(subfunction_id));
|
||||
#endif
|
||||
}
|
||||
static inline void __cpuid(int info[4], u32 function_id) { return __cpuidex(info, function_id, 0); }
|
||||
|
||||
static inline void __cpuid(int info[4], u32 function_id) {
|
||||
return __cpuidex(info, function_id, 0);
|
||||
}
|
||||
|
||||
#define _XCR_XFEATURE_ENABLED_MASK 0
|
||||
static inline u64 xgetbv(u32 index) {
|
||||
u32 eax, edx;
|
||||
@@ -56,10 +62,9 @@ static inline u64 xgetbv(u32 index) {
|
||||
return ((u64)edx << 32) | eax;
|
||||
}
|
||||
#endif // _MSC_VER
|
||||
#endif
|
||||
|
||||
namespace Common {
|
||||
#ifdef ARCHITECTURE_x86_64
|
||||
|
||||
CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string) {
|
||||
if (brand_string == "GenuineIntel") {
|
||||
return Manufacturer::Intel;
|
||||
@@ -71,53 +76,13 @@ CPUCaps::Manufacturer CPUCaps::ParseManufacturer(std::string_view brand_string)
|
||||
return Manufacturer::Unknown;
|
||||
}
|
||||
|
||||
std::optional<int> GetProcessorCount() {
|
||||
#if defined(_WIN32)
|
||||
// Get the buffer length.
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformation(nullptr, &length);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
|
||||
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||
// Now query the core count.
|
||||
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<int>(
|
||||
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
||||
return proc_info.Relationship == RelationProcessorCore;
|
||||
}));
|
||||
#elif defined(__unix__)
|
||||
const int thread_count = std::thread::hardware_concurrency();
|
||||
std::ifstream smt("/sys/devices/system/cpu/smt/active");
|
||||
char state = '0';
|
||||
if (smt) {
|
||||
smt.read(&state, sizeof(state));
|
||||
}
|
||||
switch (state) {
|
||||
case '0':
|
||||
return thread_count;
|
||||
case '1':
|
||||
return thread_count / 2;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
#else
|
||||
// Shame on you
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// @brief Detects the various CPU features
|
||||
const CPUCaps g_cpu_caps = [] {
|
||||
// Detects the various CPU features
|
||||
static CPUCaps Detect() {
|
||||
CPUCaps caps = {};
|
||||
|
||||
// Assumes the CPU supports the CPUID instruction. Those that don't would likely not support
|
||||
// yuzu at all anyway
|
||||
|
||||
int cpu_id[4];
|
||||
|
||||
// Detect CPU's CPUID capabilities and grab manufacturer string
|
||||
@@ -218,8 +183,9 @@ const CPUCaps g_cpu_caps = [] {
|
||||
// https://github.com/torvalds/linux/blob/master/tools/power/x86/turbostat/turbostat.c#L5569
|
||||
// but it's easier to just estimate the TSC tick rate for these cases.
|
||||
if (caps.tsc_crystal_ratio_denominator) {
|
||||
caps.tsc_frequency = u64(caps.crystal_frequency)
|
||||
* caps.tsc_crystal_ratio_numerator / caps.tsc_crystal_ratio_denominator;
|
||||
caps.tsc_frequency = static_cast<u64>(caps.crystal_frequency) *
|
||||
caps.tsc_crystal_ratio_numerator /
|
||||
caps.tsc_crystal_ratio_denominator;
|
||||
} else {
|
||||
caps.tsc_frequency = X64::EstimateRDTSCFrequency();
|
||||
}
|
||||
@@ -231,196 +197,54 @@ const CPUCaps g_cpu_caps = [] {
|
||||
caps.max_frequency = cpu_id[1];
|
||||
caps.bus_frequency = cpu_id[2];
|
||||
}
|
||||
|
||||
return caps;
|
||||
}();
|
||||
|
||||
#else
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept
|
||||
: rdtsc_frequency{rdtsc_frequency_}
|
||||
, ns_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency_) : 0}
|
||||
, us_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency_) : 0}
|
||||
, ms_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency_) : 0}
|
||||
, rdtsc_ns_factor{invariant_ ? GetFixedPoint64Factor(rdtsc_frequency_, NsRatio::den) : 1}
|
||||
, cntpct_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency_) : 0}
|
||||
, gputick_rdtsc_factor{invariant_ ? GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency_) : 0}
|
||||
, invariant{invariant_}
|
||||
{}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
if (!invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_rdtsc_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
if (!invariant)
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_rdtsc_factor)};
|
||||
const CPUCaps& GetCPUCaps() {
|
||||
static CPUCaps caps = Detect();
|
||||
return caps;
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
if (!invariant)
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_rdtsc_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
if (!invariant)
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
return MultiplyHigh(GetUptime(), cntpct_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
if (!invariant)
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
return MultiplyHigh(GetUptime(), gputick_rdtsc_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
if (!invariant)
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
return s64(Common::X64::FencedRDTSC());
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return invariant;
|
||||
}
|
||||
|
||||
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
|
||||
return invariant ? MultiplyHigh(ns.count(), rdtsc_ns_factor) : ns.count();
|
||||
}
|
||||
#elif defined(HAS_NCE)
|
||||
namespace {
|
||||
[[nodiscard]] Common::WallClock::FactorType GetFixedPointFactor(u64 num, u64 den) noexcept {
|
||||
return (Common::WallClock::FactorType(num) << 64) / den;
|
||||
}
|
||||
[[nodiscard]] u64 MultiplyHigh(u64 m, Common::WallClock::FactorType factor) noexcept {
|
||||
return static_cast<u64>((m * factor) >> 64);
|
||||
}
|
||||
[[nodiscard]] s64 GetHostCNTFRQ() noexcept {
|
||||
u64 cntfrq_el0 = 0;
|
||||
#ifdef __ANDROID__
|
||||
std::string_view board{""};
|
||||
char buffer[PROP_VALUE_MAX];
|
||||
int len{__system_property_get("ro.product.board", buffer)};
|
||||
board = std::string_view(buffer, static_cast<size_t>(len));
|
||||
if (board == "s5e9925") { // Exynos 2200
|
||||
cntfrq_el0 = 25600000;
|
||||
} else if (board == "exynos2100") { // Exynos 2100
|
||||
cntfrq_el0 = 26000000;
|
||||
} else if (board == "exynos9810") { // Exynos 9810
|
||||
cntfrq_el0 = 26000000;
|
||||
} else if (board == "s5e8825") { // Exynos 1280
|
||||
cntfrq_el0 = 26000000;
|
||||
} else {
|
||||
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
std::optional<int> GetProcessorCount() {
|
||||
#if defined(_WIN32)
|
||||
// Get the buffer length.
|
||||
DWORD length = 0;
|
||||
GetLogicalProcessorInformation(nullptr, &length);
|
||||
if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
std::vector<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer(
|
||||
length / sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION));
|
||||
// Now query the core count.
|
||||
if (!GetLogicalProcessorInformation(buffer.data(), &length)) {
|
||||
LOG_ERROR(Frontend, "Failed to query core count.");
|
||||
return std::nullopt;
|
||||
}
|
||||
return static_cast<int>(
|
||||
std::count_if(buffer.cbegin(), buffer.cend(), [](const auto& proc_info) {
|
||||
return proc_info.Relationship == RelationProcessorCore;
|
||||
}));
|
||||
#elif defined(__unix__)
|
||||
const int thread_count = std::thread::hardware_concurrency();
|
||||
std::ifstream smt("/sys/devices/system/cpu/smt/active");
|
||||
char state = '0';
|
||||
if (smt) {
|
||||
smt.read(&state, sizeof(state));
|
||||
}
|
||||
switch (state) {
|
||||
case '0':
|
||||
return thread_count;
|
||||
case '1':
|
||||
return thread_count / 2;
|
||||
default:
|
||||
return std::nullopt;
|
||||
}
|
||||
return cntfrq_el0;
|
||||
#else
|
||||
asm volatile("mrs %[cntfrq_el0], cntfrq_el0" : [cntfrq_el0] "=r"(cntfrq_el0));
|
||||
return cntfrq_el0;
|
||||
// Shame on you
|
||||
return std::nullopt;
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {
|
||||
const u64 host_cntfrq = std::max<u64>(GetHostCNTFRQ(), 1);
|
||||
ns_cntfrq_factor = GetFixedPointFactor(NsRatio::den, host_cntfrq);
|
||||
us_cntfrq_factor = GetFixedPointFactor(UsRatio::den, host_cntfrq);
|
||||
ms_cntfrq_factor = GetFixedPointFactor(MsRatio::den, host_cntfrq);
|
||||
cntfrq_ns_factor = GetFixedPointFactor(host_cntfrq, NsRatio::den);
|
||||
guest_cntfrq_factor = GetFixedPointFactor(CNTFRQ, host_cntfrq);
|
||||
gputick_cntfrq_factor = GetFixedPointFactor(GPUTickFreq, host_cntfrq);
|
||||
}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
return std::chrono::nanoseconds{MultiplyHigh(GetUptime(), ns_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::microseconds{MultiplyHigh(GetUptime(), us_cntfrq_factor)};
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::milliseconds{MultiplyHigh(GetUptime(), ms_cntfrq_factor)};
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return MultiplyHigh(GetUptime(), guest_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return MultiplyHigh(GetUptime(), gputick_cntfrq_factor);
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
s64 cntvct_el0 = 0;
|
||||
asm volatile(
|
||||
"dsb ish\n\t"
|
||||
"mrs %[cntvct_el0], cntvct_el0\n\t"
|
||||
"dsb ish\n\t"
|
||||
: [cntvct_el0] "=r"(cntvct_el0)
|
||||
);
|
||||
return cntvct_el0;
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
|
||||
return MultiplyHigh(ns.count(), cntfrq_ns_factor);
|
||||
}
|
||||
#else
|
||||
WallClock::WallClock(bool invariant_, u64 rdtsc_frequency_) noexcept {}
|
||||
|
||||
std::chrono::nanoseconds WallClock::GetTimeNS() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::microseconds WallClock::GetTimeUS() const {
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
std::chrono::milliseconds WallClock::GetTimeMS() const {
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now().time_since_epoch());
|
||||
}
|
||||
|
||||
s64 WallClock::GetCNTPCT() const {
|
||||
return GetUptime() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetGPUTick() const {
|
||||
return GetUptime() * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||
}
|
||||
|
||||
s64 WallClock::GetUptime() const {
|
||||
return std::chrono::duration_cast<std::chrono::nanoseconds>(std::chrono::steady_clock::now().time_since_epoch()).count();
|
||||
}
|
||||
|
||||
bool WallClock::IsNative() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
u64 WallClock::NsToTicks(std::chrono::nanoseconds ns) const {
|
||||
return ns.count();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Wall clock MUST be initialized AFTER g_cpu_caps
|
||||
// C++ only guarantees ctor init in the order they appear in TU
|
||||
const WallClock g_wall_clock = [] {
|
||||
#if defined(ARCHITECTURE_x86_64)
|
||||
auto const& caps = Common::g_cpu_caps;
|
||||
return WallClock(caps.invariant_tsc && caps.tsc_frequency >= std::nano::den, caps.tsc_frequency);
|
||||
#elif defined(HAS_NCE)
|
||||
return WallClock(false, 1);
|
||||
#else
|
||||
return WallClock(true, 1);
|
||||
#endif
|
||||
}();
|
||||
} // namespace Common
|
||||
@@ -0,0 +1,82 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-FileCopyrightText: Copyright 2013 Dolphin Emulator Project / 2015 Citra Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include "common/common_types.h"
|
||||
|
||||
namespace Common {
|
||||
|
||||
/// x86/x64 CPU capabilities that may be detected by this module
|
||||
struct CPUCaps {
|
||||
|
||||
enum class Manufacturer : u8 {
|
||||
Unknown = 0,
|
||||
Intel = 1,
|
||||
AMD = 2,
|
||||
Hygon = 3,
|
||||
};
|
||||
|
||||
static Manufacturer ParseManufacturer(std::string_view brand_string);
|
||||
|
||||
Manufacturer manufacturer;
|
||||
char brand_string[13];
|
||||
|
||||
char cpu_string[48];
|
||||
|
||||
u32 base_frequency;
|
||||
u32 max_frequency;
|
||||
u32 bus_frequency;
|
||||
|
||||
u32 tsc_crystal_ratio_denominator;
|
||||
u32 tsc_crystal_ratio_numerator;
|
||||
u32 crystal_frequency;
|
||||
u64 tsc_frequency; // Derived from the above three values
|
||||
|
||||
bool sse3 : 1;
|
||||
bool ssse3 : 1;
|
||||
bool sse4_1 : 1;
|
||||
bool sse4_2 : 1;
|
||||
|
||||
bool avx : 1;
|
||||
bool avx2 : 1;
|
||||
bool avx512f : 1;
|
||||
bool avx512dq : 1;
|
||||
bool avx512cd : 1;
|
||||
bool avx512bw : 1;
|
||||
bool avx512vl : 1;
|
||||
bool avx512vbmi : 1;
|
||||
bool avx512bitalg : 1;
|
||||
|
||||
bool aes : 1;
|
||||
bool bmi1 : 1;
|
||||
bool bmi2 : 1;
|
||||
bool f16c : 1;
|
||||
bool fma : 1;
|
||||
bool gfni : 1;
|
||||
bool invariant_tsc : 1;
|
||||
bool lzcnt : 1;
|
||||
bool monitorx : 1;
|
||||
bool movbe : 1;
|
||||
bool pclmulqdq : 1;
|
||||
bool popcnt : 1;
|
||||
bool sha : 1;
|
||||
bool waitpkg : 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the supported capabilities of the host CPU
|
||||
* @return Reference to a CPUCaps struct with the detected host CPU capabilities
|
||||
*/
|
||||
const CPUCaps& GetCPUCaps();
|
||||
|
||||
/// Detects CPU core count
|
||||
std::optional<int> GetProcessorCount();
|
||||
|
||||
} // namespace Common
|
||||
@@ -0,0 +1,75 @@
|
||||
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include <thread>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#include "common/x64/cpu_detect.h"
|
||||
#include "common/x64/cpu_wait.h"
|
||||
#include "common/x64/rdtsc.h"
|
||||
|
||||
namespace Common::X64 {
|
||||
|
||||
namespace {
|
||||
|
||||
// 100,000 cycles is a reasonable amount of time to wait to save on CPU resources.
|
||||
// For reference:
|
||||
// At 1 GHz, 100K cycles is 100us
|
||||
// At 2 GHz, 100K cycles is 50us
|
||||
// At 4 GHz, 100K cycles is 25us
|
||||
constexpr auto PauseCycles = 100'000U;
|
||||
|
||||
} // Anonymous namespace
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__clang__)
|
||||
__forceinline static void TPAUSE() {
|
||||
static constexpr auto RequestC02State = 0U;
|
||||
_tpause(RequestC02State, FencedRDTSC() + PauseCycles);
|
||||
}
|
||||
|
||||
__forceinline static void MWAITX() {
|
||||
static constexpr auto EnableWaitTimeFlag = 1U << 1;
|
||||
static constexpr auto RequestC1State = 0U;
|
||||
|
||||
// monitor_var should be aligned to a cache line.
|
||||
alignas(64) u64 monitor_var{};
|
||||
_mm_monitorx(&monitor_var, 0, 0);
|
||||
_mm_mwaitx(EnableWaitTimeFlag, RequestC1State, PauseCycles);
|
||||
}
|
||||
#else
|
||||
static void TPAUSE() {
|
||||
static constexpr auto RequestC02State = 0U;
|
||||
const auto tsc = FencedRDTSC() + PauseCycles;
|
||||
const auto eax = static_cast<u32>(tsc & 0xFFFFFFFF);
|
||||
const auto edx = static_cast<u32>(tsc >> 32);
|
||||
asm volatile("tpause %0" : : "r"(RequestC02State), "d"(edx), "a"(eax));
|
||||
}
|
||||
|
||||
static void MWAITX() {
|
||||
static constexpr auto EnableWaitTimeFlag = 1U << 1;
|
||||
static constexpr auto RequestC1State = 0U;
|
||||
|
||||
// monitor_var should be aligned to a cache line.
|
||||
alignas(64) u64 monitor_var{};
|
||||
asm volatile("monitorx" : : "a"(&monitor_var), "c"(0), "d"(0));
|
||||
asm volatile("mwaitx" : : "a"(RequestC1State), "b"(PauseCycles), "c"(EnableWaitTimeFlag));
|
||||
}
|
||||
#endif
|
||||
|
||||
void MicroSleep() {
|
||||
static const bool has_waitpkg = GetCPUCaps().waitpkg;
|
||||
static const bool has_monitorx = GetCPUCaps().monitorx;
|
||||
|
||||
if (has_waitpkg) {
|
||||
TPAUSE();
|
||||
} else if (has_monitorx) {
|
||||
MWAITX();
|
||||
} else {
|
||||
std::this_thread::yield();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Common::X64
|
||||
+5
-3
@@ -3,6 +3,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
#include <lagoon.h>
|
||||
}
|
||||
namespace Common::X64 {
|
||||
|
||||
void MicroSleep();
|
||||
|
||||
} // namespace Common::X64
|
||||
@@ -262,16 +262,20 @@ enum {
|
||||
CMP_ORD = 7,
|
||||
};
|
||||
|
||||
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) noexcept {
|
||||
u64 const distance = target - (ref + 5);
|
||||
return (distance & 0xffff'ffff) == distance;
|
||||
constexpr bool IsWithin2G(uintptr_t ref, uintptr_t target) {
|
||||
const u64 distance = target - (ref + 5);
|
||||
return !(distance >= 0x8000'0000ULL && distance <= ~0x8000'0000ULL);
|
||||
}
|
||||
|
||||
inline bool IsWithin2G(const Xbyak::CodeGenerator& code, uintptr_t target) {
|
||||
return IsWithin2G(reinterpret_cast<uintptr_t>(code.getCurr()), target);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void CallFarFunction(Xbyak::CodeGenerator& code, const T f) {
|
||||
static_assert(std::is_pointer_v<T>, "Argument must be a (function) pointer.");
|
||||
uintptr_t addr = uintptr_t(f);
|
||||
if (IsWithin2G(uintptr_t(code.getCurr()), addr)) {
|
||||
size_t addr = reinterpret_cast<size_t>(f);
|
||||
if (IsWithin2G(code, addr)) {
|
||||
code.call(f);
|
||||
} else {
|
||||
// ABI_RETURN is a safe temp register to use before a call
|
||||
|
||||
@@ -1200,7 +1200,7 @@ else()
|
||||
$<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type>
|
||||
$<$<CXX_COMPILER_ID:Clang>:-fsized-deallocation>)
|
||||
# pre-clang19 will spam with "OH DID YOU MEAN THIS?" otherwise...
|
||||
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
|
||||
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 19)
|
||||
target_compile_options(core PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>)
|
||||
endif()
|
||||
endif()
|
||||
@@ -1215,7 +1215,6 @@ else()
|
||||
endif()
|
||||
|
||||
target_link_libraries(core PRIVATE
|
||||
OpenSSL::SSL
|
||||
fmt::fmt
|
||||
nlohmann_json::nlohmann_json
|
||||
RenderDoc::API
|
||||
@@ -1247,7 +1246,7 @@ if (HAS_NCE)
|
||||
target_link_libraries(core PRIVATE merry::oaknut)
|
||||
endif()
|
||||
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64 OR ARCHITECTURE_loongarch64)
|
||||
if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64 OR ARCHITECTURE_riscv64)
|
||||
target_sources(core PRIVATE
|
||||
arm/dynarmic/arm_dynarmic.h
|
||||
arm/dynarmic/arm_dynarmic_64.cpp
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user