Compare commits

..

20 Commits

Author SHA1 Message Date
Eden CI a32d2f647c Update dependencies
* openssl-cmake: 3.6.2 -> 4.0.0
* openssl: 3.6.2 -> 4.0.0
* boost: 1.90.0 -> 1.91.0
* vulkan-validation-layers: 1.4.341.0 -> 1.4.350.0
* sirit: 1.0.4 -> 1.0.5
* httplib: 0.37.0 -> 0.46.1
* xbyak: 7.35.2 -> 7.37.3
* catch2: 3.13.0 -> 3.15.0
* sdl3: 3.4.8 -> 3.4.10
* libusb: 1.0.29 -> 1.0.30
* vulkan-headers: 1.4.345 -> 1.4.352
* vulkan-utility-libraries: 1.4.345 -> 1.4.352
2026-06-01 23:26:35 -04:00
crueter 7a18b1c127 wot
Signed-off-by: crueter <crueter@eden-emu.dev>
2026-06-01 23:25:04 -04:00
crueter 5783427842 fix openssl
Signed-off-by: crueter <crueter@eden-emu.dev>
2026-06-01 23:24:55 -04:00
crueter aff9a6cee1 update cpmutil
Signed-off-by: crueter <crueter@eden-emu.dev>
2026-06-01 23:20:51 -04:00
crueter 060ebb8ad4 [ci] Fix update-deps workflow
me when spaces
2026-06-02 05:02:49 +02:00
crueter cc8451f764 [desktop] Rework game list to use MVP architecture (#4042)
Closes #3480

moves the game list model/worker/private stuff to qt_common for later
use in QML

- `qt_common/game_list/model.{cpp,h}` is the model
- `yuzu/game/game_{grid,tree}.*` are the views
- `yuzu/game/game_list.cpp` is the presenter

This was done very lazily in a manner that "works" while largely
maintaining existing structure as much as possible. Most of it is
copy-paste, with some bonus reworks/cleanups thrown in.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4042
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 04:08:24 +02:00
crueter 27189f39d2 [desktop] Prefer extracred folder name over zip name for non-Atmosphere zip mods (#4043)
e.g. Serfrost's Defogger will now be named "Serfrosts Defogger" by
default, instead of "serfrosts_base_defogger_v2-4"

Note that for atmosphere mods it still uses the zip folder name, since otherwise their default name will just be the game's Title ID.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4043
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 04:08:09 +02:00
crueter 683e6249c3 [cmake] Allow building OpenSSL from source (#4032)
If YUZU_USE_BUNDLED_OPENSSL is off and OpenSSL is *not* installed to the
system, pulls in OpenSSL and Jimmy Park's CMake wrapper, then configures + builds from source.

Some patches were made on top of OpenSSL and openssl-cmake:
- USE_CCACHE is respected from UseCcache.cmake
- CXX/CFLAGS are passed from CMake to the configure script, which sends
  those to the compiler
- Uses a bundled cert.h akin to the bundled OpenSSL build

Closes #3614

~~Before merge: remove verbose stuff~~ actually useful so nvm

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4032
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 03:40:28 +02:00
crueter eaece15dbd [svc] Stub BreakDebugProcess (#4044)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4044
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
2026-06-02 03:33:38 +02:00
xbzk 8e5419209c [video,buffer] rewrite storagebufferbinding size() lambda to be full data driven instead of cbuf_index based (#4041)
fixes an yxzx era bug where eden assumed NVN-style packed SSBO descriptors (u64 gpu_addr followed by size) only happen in cbuf_index == 0.

Mega Man Star Force Collection proves that assumption is false. It has an unbiased/global-memory SSBO descriptor in cbuf_index == 3, offsets 0x100/0x300, but the descriptor still appears to be { address, size }.

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4041
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 03:31:59 +02:00
lizzie 8fac95dcc0 [vk] Fix regressions introduced by #3997 w.r.t to marked stages for pipeline barriers (#4037)
evil barriers :)

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4037
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 01:28:39 +02:00
crueter 706a3d0764 [cmake] Disable no-cast-function-type-mismatch on Clang 19 (#4038)
Suppresses this annoying warning during Android builds

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4038
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-06-02 01:28:16 +02:00
CamilleLaVey 3d19743d95 [vulkan] Fix regressions found in last stable release (#3953)
This PR aims to fix some regressions found in the latest release 0.2.0, which were a bunch of constant crashes/ random on certain Android devices with issues with the PiP configuration, addressing some problems founds for AMD after the maintenance of 2nd Global Vulkan Maintenance.

-> Fixes Final Fantasy Tactics on AMD (no longer requires of generic bits to work "all commands bit")
-> Fixes some performance regressions on android due to the Tomodachi fix applied globally as common behavior (#3898, #3900)
-> Fixes blittering of screen found on ARM Windows devices and QCOM stock drivers (Android and ARM Windows) related to Mario Kart 8 Deluxe strange blittering in races, caused by a strange race condition with the ResetQueryPool and mostly the workaround for presync
-> Fixes issues on Luigi's Mansion 3 issue where the pause screen became black on AMD due to the early reset of queries.
-> Fixes crashes on Mario Party Jamboree for AMD/ Nvidia.
-> Keeps previous fixes related to crashes on AMD with other games such as Astral Chain, Fire Emblem Three Houses and Xenoblade 3 based on the lack of access to vertex fragment replaced with generic flags.
-> Fixes TOTK RADV skybox lighting.

--------
Credits:
@melod-y
@Gidoly
@MaranBr
@AlexWolff
@Lizzie

And all the people who contributed into the reporting issues/ helping with the bisect.

Co-authored-by: lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3953
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-06-02 01:06:12 +02:00
crueter bd2d344040 [desktop] Restore metal layer search (#4033)
This was cut out in #3916 by accident.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4033
2026-05-31 04:19:49 +02:00
lizzie 5f4a286046 [dynarmic] cleanup duplicate code and reimpls of std::* bit stuff (#4017)
A bit of a minor cleanup
- std::rotr instead of mcl::bit::rotate_right
- std::rotl likewise
- std::popcount instaed of "count ones"
- use ConvertRoundingModeToX64Immediate where appropiate
- std integral

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4017
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 04:18:12 +02:00
crueter b7fcec4985 [desktop] Increase rlimit on UNIX/Apple (#4030)
Sets max open fd limit to 8192 on non-windows platforms (or bounds it to
the system hard limit). Complement to the previous VFS PR.

Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4030
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-31 04:13:56 +02:00
MaranBr 0473747f94 [am] Fix application state notification (#4027)
This fixed issues in Mario Kart 8 multiplayer where the native controller applet would pop up, then once A was pressed and it exited, it would freeze the game but music would continue playing.

The issue was that UpdateRequestedFocusState() updates the focus state but never sets m_has_focus_state_changed for applications. Since ShouldSignalSystemEvent() checks that flag for applications, they never receive FocusStateChanged messages when LLE library applets exit. The game keeps running (hence the music) but is stuck waiting for a focus notification that never arrives. HLE applets aren't affected because their dummy process has is_process_running=false, so the game is never considered obscured in the first place.

Credits: [davidcollini](https://github.com/davidcollini)

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4027
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 03:55:12 +02:00
lizzie 23bb909bc9 [audio_core] fix OOB copy when silencing channel on shutdown (#3969)
when shutting down the emulator will silence any remaining audio from the output buffer
however this is for some reason stored in an array instead of being a simple memset
additionally, said array can be small enough (`frame_size_bytes > silence.size()`) to cause a funky noise to play at the end

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3969
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 02:38:26 +02:00
lizzie e94ac63a5e [common/thread] fix MSVC build error with _rdstc (#4029)
fixes issue reported by @bruno

Signed-off-by: lizzie <lizzie@eden-emu.dev>

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4029
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: crueter <crueter@eden-emu.dev>
2026-05-31 02:32:21 +02:00
Eden CI 88ff086d13 [dist, android] Update translations from Transifex for May 30 (#4028)
Automatic translation update for May 30

Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4028
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
2026-05-31 02:32:12 +02:00
131 changed files with 14987 additions and 10012 deletions
+2 -1
View File
@@ -37,6 +37,7 @@ jobs:
- name: Create PR
run: |
set -x
DATE=$(date +"%b %d")
TITLE="[dist, android] Update translations from Transifex for $DATE"
BODY="Automatic translation update for $DATE"
@@ -52,7 +53,7 @@ jobs:
}
EOF
curl -X 'POST' \
curl -XPOST \
'https://git.eden-emu.dev/api/v1/repos/eden-emu/eden/pulls' \
-H 'accept: application/json' \
-H 'Authorization: Bearer ${{ secrets.CI_FJ_TOKEN }}' \
+3 -1
View File
@@ -24,9 +24,11 @@ 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-$DATE
git switch -c update-deps-$TIMESTAMP
tools/cpmutil.sh package update -ac
git push
@@ -0,0 +1,214 @@
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
@@ -0,0 +1,54 @@
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
@@ -0,0 +1,28 @@
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
File diff suppressed because it is too large Load Diff
+9 -2
View File
@@ -383,13 +383,20 @@ 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)
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
AddJsonPackage(openssl-cmake)
endif()
endif()
find_package(OpenSSL 3 REQUIRED)
if (OpenSSL_ADDED)
add_compile_definitions(YUZU_BUNDLED_OPENSSL)
endif()
message(STATUS "Fetching needed dependencies with CPM")
+51 -29
View File
@@ -3,7 +3,7 @@
set(CPM_SOURCE_CACHE "${PROJECT_SOURCE_DIR}/.cache/cpm" CACHE STRING "" FORCE)
if(MSVC OR ANDROID)
if(MSVC OR ANDROID OR IOS)
set(BUNDLED_DEFAULT ON)
else()
set(BUNDLED_DEFAULT OFF)
@@ -128,7 +128,8 @@ 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 the following packages to your system if available:"
"1. Install or upgrade 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"
@@ -247,7 +248,9 @@ function(AddJsonPackage)
set(multiValueArgs OPTIONS)
cmake_parse_arguments(JSON "" "${oneValueArgs}" "${multiValueArgs}"
set(optionArgs MODULE)
cmake_parse_arguments(JSON "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}"
"${ARGN}")
list(LENGTH ARGN argnLength)
@@ -276,6 +279,10 @@ function(AddJsonPackage)
parse_object(${object})
if (JSON_MODULE)
set(EXTRA_ARGS MODULE)
endif()
if(ci)
AddCIPackage(
VERSION ${version}
@@ -284,8 +291,8 @@ function(AddJsonPackage)
PACKAGE ${package}
EXTENSION ${extension}
MIN_VERSION ${min_version}
DISABLED_PLATFORMS ${disabled_platforms})
DISABLED_PLATFORMS ${disabled_platforms}
${EXTRA_ARGS})
else()
if (NOT DEFINED JSON_FORCE_BUNDLED_PACKAGE)
set(JSON_FORCE_BUNDLED_PACKAGE OFF)
@@ -307,23 +314,24 @@ 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})
ARTIFACT "${artifact}"
TAG "${tag}"
${EXTRA_ARGS})
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()
# TODO(crueter): git clone?
set(EXTRA_ARGS "")
#[[
URL configurations, descending order of precedence:
@@ -368,7 +376,9 @@ function(AddPackage)
set(multiValueArgs OPTIONS PATCHES)
cmake_parse_arguments(PKG_ARGS "" "${oneValueArgs}" "${multiValueArgs}"
set(optionArgs MODULE)
cmake_parse_arguments(PKG_ARGS "${optionArgs}" "${oneValueArgs}" "${multiValueArgs}"
"${ARGN}")
if(NOT DEFINED PKG_ARGS_NAME)
@@ -552,6 +562,12 @@ 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}
@@ -601,13 +617,14 @@ function(AddPackage)
endif()
# pass stuff to parent scope
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)
Propagate(${PKG_ARGS_NAME}_ADDED)
Propagate(${PKG_ARGS_NAME}_SOURCE_DIR)
Propagate(${PKG_ARGS_NAME}_BINARY_DIR)
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?
@@ -690,14 +707,20 @@ function(AddCIPackage)
set(pkgname linux-amd64)
elseif(PLATFORM_LINUX AND ARCHITECTURE_arm64)
set(pkgname linux-aarch64)
elseif(APPLE)
elseif(APPLE AND NOT IOS)
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}
@@ -708,23 +731,22 @@ function(AddCIPackage)
KEY "${pkgname}-${ARTIFACT_VERSION}"
HASH_SUFFIX sha512sum
FORCE_BUNDLED_PACKAGE ON
DOWNLOAD_ONLY ${PKG_ARGS_MODULE})
${EXTRA_ARGS})
set(${ARTIFACT_PACKAGE}_ADDED TRUE PARENT_SCOPE)
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()
Propagate(${ARTIFACT_PACKAGE}_SOURCE_DIR)
Propagate(CMAKE_PREFIX_PATH)
else()
find_package(${ARTIFACT_PACKAGE} ${ARTIFACT_MIN_VERSION} REQUIRED)
endif()
endfunction()
# Utility function for Qt
function(AddQt version)
function(AddQt repo version)
if (NOT DEFINED repo)
message(FATAL_ERROR "[CPMUtil] AddQt: repo is required")
endif()
if (NOT DEFINED version)
message(FATAL_ERROR "[CPMUtil] AddQt: version is required")
endif()
@@ -734,7 +756,7 @@ function(AddQt version)
PACKAGE Qt6
VERSION ${version}
MIN_VERSION 6
REPO crueter-ci/Qt
REPO ${repo}
DISABLED_PLATFORMS
android-x86_64 android-aarch64
freebsd-amd64 solaris-amd64 openbsd-amd64
+32 -5
View File
@@ -1,5 +1,5 @@
{
"openssl": {
"openssl-ci": {
"ci": true,
"package": "OpenSSL",
"name": "openssl",
@@ -7,13 +7,40 @@
"version": "3.6.0-1cb0d36b39",
"min_version": "3"
},
"openssl-cmake": {
"repo": "jimmy-park/openssl-cmake",
"hash": "c8bc3001497ada490065a18bca4c2ed7326701da3372c1d2c167e9853d43ad107341f97939b67eaa9cb4f2d9637cacbfb9f4ac5a52d9402a1605a6de05756345",
"git_version": "4.0.0",
"tag": "%VERSION%",
"bundled": true,
"options": [
"OPENSSL_CONFIGURE_OPTIONS threads"
],
"patches": [
"0001-cpmutil-compat.patch",
"0002-use-ccache.patch",
"0003-use-cmake-compiler-flags.patch"
]
},
"openssl": {
"repo": "openssl/openssl",
"package": "OpenSSL",
"min_version": "3",
"version": "3",
"hash": "e50bcb288436dc9fe35feff7fe3ce293a67cd168aa5c3a66cb24acd94f55c3dc3bc0be5be402432daf58605d2fb42805105d0e601519ca6e696f2b74b9f06911",
"git_version": "4.0.0",
"tag": "openssl-%VERSION%",
"patches": [
"0001-add-bundled-cert.patch"
]
},
"boost": {
"package": "Boost",
"repo": "boostorg/boost",
"tag": "boost-%VERSION%",
"artifact": "%TAG%-cmake.tar.xz",
"hash": "6ae6e94664fe7f2fb01976b59b276ac5df8085c7503fa829d810fbfe495960cfec44fa2c36e2cb23480bc19c956ed199d4952b02639a00a6c07625d4e7130c2d",
"git_version": "1.90.0",
"hash": "935b3d516e996f6d25948ba8a54c1b7f70f7f0e3f517e36481fdf0196c2c5cfc2841f86e891f3df9517746b7fb605db47cdded1b8ff78d9482ddaa621db43a34",
"git_version": "1.91.0",
"version": "1.57",
"find_args": "CONFIG OPTIONAL_COMPONENTS headers context system fiber filesystem",
"patches": [
@@ -98,9 +125,9 @@
"package": "VVL",
"repo": "KhronosGroup/Vulkan-ValidationLayers",
"tag": "vulkan-sdk-%VERSION%",
"git_version": "1.4.341.0",
"git_version": "1.4.350.0",
"artifact": "android-binaries-%VERSION%.zip",
"hash": "8812ae84cbe49e6a3418ade9c458d3be6d74a3dffd319d4502007b564d580998056e8190414368ec11b27bc83993c7a0dad713c31bcc3d9553b51243efee3753"
"hash": "5cbed0369d4c325c8ea9ab5a1d78d98ec721bdfae4d772dac23803f31aa909be6e132fca3b64d507e6b9835f9be9d0848407adbf74365fd3f37ae99add502d21"
},
"quazip": {
"package": "QuaZip-Qt6",
+346 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+352 -321
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+346 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+345 -315
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+346 -316
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -18,3 +18,4 @@
- `linux-amd64`
- `linux-aarch64`
- `macos-universal`
- `ios-aarch64`
+2 -1
View File
@@ -61,7 +61,8 @@ 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"
"macos-universal",
"ios-aarch64"
]
},
"boost": {
+15 -15
View File
@@ -9,7 +9,7 @@
},
"sirit": {
"repo": "eden-emulator/sirit",
"git_version": "1.0.4",
"git_version": "1.0.5",
"tag": "v%VERSION%",
"artifact": "sirit-source-%VERSION%.tar.zst",
"hash_suffix": "sha512sum",
@@ -28,8 +28,8 @@
"httplib": {
"repo": "yhirose/cpp-httplib",
"tag": "v%VERSION%",
"hash": "5efa8140aadffe105dcf39935b732476e95755f6c7473ada3d0b64df2bc02c557633ae3948a25b45e1cf67e89a3ff6329fb30362e4ac033b9a1d1e453aa2eded",
"git_version": "0.37.0",
"hash": "5133e3378b8b26c12e0634bb4782d3a5f6e98530149a3b2e54e18955ffd17e3997fd6196e6a4351d7ea1d4fa1826760418a92f9849b0b4a2d52308f6e0670b5d",
"git_version": "0.46.1",
"find_args": "MODULE GLOBAL",
"patches": [
"0001-mingw.patch",
@@ -57,8 +57,8 @@
"package": "xbyak",
"repo": "herumi/xbyak",
"tag": "v%VERSION%",
"hash": "b6475276b2faaeb315734ea8f4f8bd87ededcee768961b39679bee547e7f3e98884d8b7851e176d861dab30a80a76e6ea302f8c111483607dde969b4797ea95a",
"git_version": "7.35.2"
"hash": "03d870f63741ff8c00501329bf9947bdf58e7cc4c3884e3de9b827f31942438887555f601a5f80d405946854eb54ab907b4e2a3ad955ca4ad890a243917dd4ae",
"git_version": "7.37.3"
},
"oaknut": {
"repo": "eden-emulator/oaknut",
@@ -140,9 +140,9 @@
"package": "Catch2",
"repo": "catchorg/Catch2",
"tag": "v%VERSION%",
"hash": "7eea385d79d88a5690cde131fe7ccda97d5c54ea09d6f515000d7bf07c828809d61c1ac99912c1ee507cf933f61c1c47ecdcc45df7850ffa82714034b0fccf35",
"hash": "09df8b291d0c756c492871ce0a4fb5c703162d1364a9864470b227d4d19d9865a0ba5293a5f38d0117cbc7c230f42be35db9f6e0ca5d889dff02f1745807f380",
"version": "3.0.1",
"git_version": "3.13.0",
"git_version": "3.15.0",
"patches": [
"0001-solaris-isnan-fix.patch"
]
@@ -166,8 +166,8 @@
"package": "SDL3",
"repo": "libsdl-org/SDL",
"tag": "release-%VERSION%",
"hash": "df5a323af7ac366661a3c0e887969c72584d232f3cc211419d59b0487b620b6b2859d4549c9e8df002ee489290062e466fcfddf7edc0872a37b1f2845e81c0f3",
"git_version": "3.4.8",
"hash": "10a9c1fa4d6891c7387fa694b786a168f86b6e5447c6c522f85b739e33720e106ee879dfa9e6e537d5521b983cfbd4908927c555c4d3412735129a4231e16fe6",
"git_version": "3.4.10",
"version": "3.2.10"
},
"moltenvk": {
@@ -195,9 +195,9 @@
"libusb": {
"repo": "libusb/libusb",
"tag": "v%VERSION%",
"hash": "98c5f7940ff06b25c9aa65aa98e23de4c79a4c1067595f4c73cc145af23a1c286639e1ba11185cd91bab702081f307b973f08a4c9746576dc8d01b3620a3aeb5",
"hash": "3251c9f41e900efa13caf981483f46886c8434bf4c30f3fd3073921b06be9977cebcf4a18f7bc46db86e33d7f19752296377be9050abfb8d887ffeb377864647",
"find_args": "MODULE",
"git_version": "1.0.29",
"git_version": "1.0.30",
"patches": [
"0001-netbsd-gettime.patch"
]
@@ -230,15 +230,15 @@
"repo": "KhronosGroup/Vulkan-Headers",
"package": "VulkanHeaders",
"version": "1.4.317",
"hash": "d2846ea228415772645eea4b52a9efd33e6a563043dd3de059e798be6391a8f0ca089f455ae420ff22574939ed0f48ed7c6ff3d5a9987d5231dbf3b3f89b484b",
"git_version": "1.4.345",
"hash": "dbb7a6def360aebc2a14df5cdeab0fe6455f37d7885d451a0aa307e82ea46193c262f77a79bea6a45530286d225b03687880a11e857279f339437069b866fa82",
"git_version": "1.4.352",
"tag": "v%VERSION%"
},
"vulkan-utility-libraries": {
"repo": "KhronosGroup/Vulkan-Utility-Libraries",
"package": "VulkanUtilityLibraries",
"hash": "114f6b237a6dcba923ccc576befb5dea3f1c9b3a30de7dc741f234a831d1c2d52d8a224afb37dd57dffca67ac0df461eaaab6a5ab5e503b393f91c166680c3e1",
"git_version": "1.4.345",
"hash": "4aaaba1e6ffd235bdc2d7ae5dfdebb3024ff011c47157d838d839ea8c6824af5b5a26f4771c7fdc83a883b69ce766f993bba3ecad7dde2dec102c238e68f6210",
"git_version": "1.4.352",
"tag": "v%VERSION%"
},
"frozen": {
@@ -15,7 +15,6 @@ 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
@@ -101,7 +100,6 @@ 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) {
@@ -270,18 +268,12 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
}
override fun onUserLeaveHint() {
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())
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())
}
}
}
@@ -661,29 +653,7 @@ 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) {
@@ -693,9 +663,7 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener, InputManager
BooleanSetting.PICTURE_IN_PICTURE.getBoolean() && isEmulationActive
)
}
runPictureInPictureAction("set picture-in-picture params") {
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
}
setPictureInPictureParams(pictureInPictureParamsBuilder.build())
}
fun displayMultiplayerDialog() {
@@ -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</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام التباين الديناميكي لـ FSR</string>
<string name="fsr_sharpness">حدة FSR/SGSR</string>
<string name="fsr_sharpness_description">يحدد مدى وضوح الصورة عند استخدام مرشحات FSR أو SGSR</string>
<string name="renderer_anti_aliasing">طريقة مضاد التعرج</string>
@@ -503,6 +503,8 @@
<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,8 +329,6 @@
<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,8 +439,6 @@
<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,8 +439,6 @@ 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 de sistema usando el firmware instalado</string>
<string name="applets_description">Ejecutar applets del 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</string>
<string name="fsr_sharpness_description">Ajusta la intensidad del filtro de enfoque al usar el contraste dinámico de FSR.</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="renderer_anti_aliasing">Método de suavizado de bordes</string>
@@ -497,6 +497,8 @@
<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>
@@ -1072,7 +1074,7 @@
<!-- Black backgrounds theme -->
<string name="use_black_backgrounds">Fondos oscuros</string>
<string name="use_black_backgrounds_description">Cuando utilice el modo oscuro, aplique fondos negros.</string>
<string name="use_black_backgrounds_description">Cuando se usa el modo oscuro, aplicar fondos de pantalla negros.</string>
<!-- Buttons -->
<string name="enable_folder_button">Carpeta</string>
@@ -454,8 +454,6 @@
<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,8 +359,6 @@
<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,8 +348,6 @@
<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,8 +380,6 @@
<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,8 +387,6 @@
<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,8 +329,6 @@
<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,8 +439,6 @@
<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,8 +430,6 @@
<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,8 +352,6 @@
<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</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR.</string>
<string name="fsr_sharpness">Резкость FSR/SGSR</string>
<string name="fsr_sharpness_description">Определяет, насколько чётким будет изображение при использовании динамического контраста FSR или SGSR фильтров</string>
<string name="renderer_anti_aliasing">Метод сглаживания</string>
@@ -499,6 +499,8 @@
<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,8 +351,6 @@
<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</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні FSR.</string>
<string name="fsr_sharpness">Різкість FSR/SGSR</string>
<string name="fsr_sharpness_description">Визначає різкість зображення при використанні фільтрів FSR або SGSR.</string>
<string name="renderer_anti_aliasing">Згладжування</string>
@@ -499,6 +499,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 під час оновлення пам\'яті, зменшуючи навантаження на процесор і покращуючи продуктивність. Може спричинити збої в деяких іграх.</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 A6XXA7XX / Turnip), прибирає світіння в Burnout. Увага: може спричинити графічні артефакти в інших іграх.</string>
<string name="emulate_bgr565">Емулювати BGR565</string>
@@ -327,8 +327,6 @@
<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 锐</string>
<string name="fsr_sharpness_description">确定使用 FSR 的动态对比度功能时的图像锐化程</string>
<string name="fsr_sharpness">FSR/SGSR 锐度</string>
<string name="fsr_sharpness_description">确定使用 FSR 或 SGSR 过滤器时的图像锐度</string>
<string name="renderer_anti_aliasing">抗锯齿方式</string>
@@ -493,6 +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">减少《塞尔达传说:智慧的再现》(Adreno A6XX - A7XX/ Turnip)中的 bloom 模糊,并移除《Burnout》中的 bloom 效果。警告:可能会导致在其他游戏中出现图形异常。</string>
<string name="emulate_bgr565">模拟 BGR565</string>
@@ -437,8 +437,6 @@
<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>
+2 -4
View File
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
@@ -177,10 +177,8 @@ 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::memcpy(&output_buffer[i * frame_size], silence.data(), frame_size_bytes);
std::memset(&output_buffer[i * frame_size], 0, frame_size_bytes);
return;
}
+9
View File
@@ -184,7 +184,11 @@ bool Event::WaitFor(const std::chrono::nanoseconds time) {
_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
@@ -213,8 +217,13 @@ bool Event::WaitFor(const std::chrono::nanoseconds time) {
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;
+1 -1
View File
@@ -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 19)
if (CXX_CLANG AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL 20)
target_compile_options(core PRIVATE $<$<COMPILE_LANGUAGE:C,CXX>:-Wno-cast-function-type-mismatch>)
endif()
endif()
+5 -2
View File
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -12,8 +15,8 @@ Result DebugActiveProcess(Core::System& system, Handle* out_handle, uint64_t pro
}
Result BreakDebugProcess(Core::System& system, Handle debug_handle) {
UNIMPLEMENTED();
R_THROW(ResultNotImplemented);
LOG_WARNING(Service, "(STUBBED) called");
R_SUCCEED();
}
Result TerminateDebugProcess(Core::System& system, Handle debug_handle) {
@@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@@ -372,6 +375,10 @@ bool LifecycleManager::UpdateRequestedFocusState() {
// Mark the focus state as ready for update.
m_requested_focus_state = new_state;
if (m_is_application) {
m_has_focus_state_changed = true;
}
// We changed the focus state.
return true;
}
@@ -24,7 +24,7 @@ using DoNotFastmemMarker = std::tuple<IR::LocationDescriptor, unsigned>;
constexpr std::size_t xmrx(std::size_t x) noexcept {
x ^= x >> 32;
x *= 0xff51afd7ed558ccd;
x ^= mcl::bit::rotate_right(x, 47) ^ mcl::bit::rotate_right(x, 23);
x ^= std::rotr(x, 47) ^ std::rotr(x, 23);
return x;
}
@@ -1532,7 +1532,7 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) {
if (ctx.FPCR().DN()) {
ForceToDefaultNaN<32>(code, result);
}
code.vcvtps2ph(result, result, static_cast<u8>(*round_imm));
code.vcvtps2ph(result, result, u8(*round_imm));
ctx.reg_alloc.DefineValue(code, inst, result);
return;
@@ -1540,7 +1540,7 @@ void EmitX64::EmitFPSingleToHalf(EmitContext& ctx, IR::Inst* inst) {
ctx.reg_alloc.HostCall(code, inst, args[0]);
code.mov(code.ABI_PARAM2.cvt32(), ctx.FPCR().Value());
code.mov(code.ABI_PARAM3.cvt32(), static_cast<u32>(rounding_mode));
code.mov(code.ABI_PARAM3.cvt32(), u32(rounding_mode));
code.lea(code.ABI_PARAM4, code.ptr[code.ABI_JIT_PTR + code.GetJitStateInfo().offsetof_fpsr_exc]);
code.CallFunction(&FP::FPConvert<u16, u32>);
}
@@ -38,7 +38,7 @@ void EmitSignedSaturatedOp(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst)
Xbyak::Reg addend = ctx.reg_alloc.UseGpr(code, args[1]).changeBit(size);
Xbyak::Reg overflow = ctx.reg_alloc.ScratchGpr(code).changeBit(size);
constexpr u64 int_max = static_cast<u64>((std::numeric_limits<mcl::signed_integer_of_size<size>>::max)());
constexpr u64 int_max = u64((std::numeric_limits<std::make_signed_t<mcl::unsigned_integer_of_size<size>>>::max)());
if constexpr (size < 64) {
code.xor_(overflow.cvt32(), overflow.cvt32());
code.bt(result.cvt32(), size - 1);
@@ -3553,7 +3553,7 @@ void EmitX64::EmitVectorPopulationCount(EmitContext& ctx, IR::Inst* inst) {
EmitOneArgumentFallback(code, ctx, inst, [](VectorArray<u8>& result, const VectorArray<u8>& a) {
std::transform(a.begin(), a.end(), result.begin(), [](u8 val) {
return static_cast<u8>(mcl::bit::count_ones(val));
return static_cast<u8>(std::popcount(val));
});
});
}
@@ -1657,20 +1657,10 @@ void EmitFPVectorRoundInt(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
if constexpr (fsize != 16) {
if (code.HasHostFeature(HostFeature::SSE41) && rounding != FP::RoundingMode::ToNearest_TieAwayFromZero && !exact) {
const u8 round_imm = [&]() -> u8 {
switch (rounding) {
case FP::RoundingMode::ToNearest_TieEven: return 0b00;
case FP::RoundingMode::TowardsPlusInfinity: return 0b10;
case FP::RoundingMode::TowardsMinusInfinity: return 0b01;
case FP::RoundingMode::TowardsZero: return 0b11;
default: UNREACHABLE();
}
}();
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding);
EmitTwoOpVectorOperation<fsize, DefaultIndexer, 3>(code, ctx, inst, [&](const Xbyak::Xmm& result, const Xbyak::Xmm& xmm_a) {
FCODE(roundp)(result, xmm_a, round_imm);
FCODE(roundp)(result, xmm_a, *round_imm);
});
return;
}
}
@@ -2002,19 +1992,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
auto args = ctx.reg_alloc.GetArgumentInfo(inst);
const Xbyak::Xmm src = ctx.reg_alloc.UseScratchXmm(code, args[0]);
MaybeStandardFPSCRValue(code, ctx, fpcr_controlled, [&] {
const int round_imm = [&] {
switch (rounding) {
case FP::RoundingMode::ToNearest_TieEven:
default:
return 0b00;
case FP::RoundingMode::TowardsPlusInfinity:
return 0b10;
case FP::RoundingMode::TowardsMinusInfinity:
return 0b01;
case FP::RoundingMode::TowardsZero:
return 0b11;
}
}();
const auto round_imm = ConvertRoundingModeToX64Immediate(rounding);
const auto perform_conversion = [&code, &ctx](const Xbyak::Xmm& src) {
// MSVC doesn't allow us to use a [&] capture, so we have to do this instead.
(void)ctx;
@@ -2046,7 +2024,7 @@ void EmitFPVectorToFixed(BlockOfCode& code, EmitContext& ctx, IR::Inst* inst) {
FCODE(mulp)(src, GetVectorOf<fsize>(code, scale_factor));
}
FCODE(roundp)(src, src, u8(round_imm));
FCODE(roundp)(src, src, u8(*round_imm));
const Xbyak::Xmm nan_mask = xmm0;
if (code.HasHostFeature(HostFeature::AVX512_OrthoFloat)) {
static constexpr u32 nan_to_zero = FixupLUT(FpFixup::PosZero, FpFixup::PosZero);
@@ -52,7 +52,7 @@ struct TranslatorVisitor final {
u32 imm32 = imm8.ZeroExtend();
auto carry_out = carry_in;
if (rotate) {
imm32 = mcl::bit::rotate_right<u32>(imm8.ZeroExtend(), rotate * 2);
imm32 = std::rotr<u32>(imm8.ZeroExtend(), rotate * 2);
carry_out = ir.Imm1(mcl::bit::get_bit<31>(imm32));
}
return {imm32, carry_out};
@@ -81,7 +81,7 @@ struct TranslatorVisitor final {
}();
return {imm32, carry_in};
}
const u32 imm32 = mcl::bit::rotate_right<u32>((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>());
const u32 imm32 = std::rotr<u32>((1 << 7) | imm12.Bits<0, 6>(), imm12.Bits<7, 11>());
return {imm32, ir.Imm1(mcl::bit::get_bit<31>(imm32))};
}
@@ -79,7 +79,7 @@ bool TranslatorVisitor::asimd_VDUP_scalar(bool D, Imm<4> imm4, size_t Vd, bool Q
return UndefinedInstruction();
}
const size_t imm4_lsb = mcl::bit::lowest_set_bit(imm4.ZeroExtend());
const size_t imm4_lsb = std::countr_zero(imm4.ZeroExtend());
const size_t esize = 8u << imm4_lsb;
const size_t index = imm4.ZeroExtend() >> (imm4_lsb + 1);
const auto d = ToVector(Q, Vd, D);
@@ -799,7 +799,7 @@ static bool LDMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s
// LDM <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
@@ -811,13 +811,13 @@ bool TranslatorVisitor::arm_LDM(Cond cond, bool W, Reg n, RegList list) {
}
const auto start_address = ir.GetRegister(n);
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(mcl::bit::count_ones(list) * 4)));
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(std::popcount(list) * 4)));
return LDMHelper(ir, W, n, list, start_address, writeback_address);
}
// LDMDA <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
@@ -828,14 +828,14 @@ bool TranslatorVisitor::arm_LDMDA(Cond cond, bool W, Reg n, RegList list) {
return true;
}
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list) - 4)));
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list) - 4)));
const auto writeback_address = ir.Sub(start_address, ir.Imm32(4));
return LDMHelper(ir, W, n, list, start_address, writeback_address);
}
// LDMDB <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
@@ -846,14 +846,14 @@ bool TranslatorVisitor::arm_LDMDB(Cond cond, bool W, Reg n, RegList list) {
return true;
}
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
const auto writeback_address = start_address;
return LDMHelper(ir, W, n, list, start_address, writeback_address);
}
// LDMIB <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
if (W && mcl::bit::get_bit(static_cast<size_t>(n), list)) {
@@ -865,7 +865,7 @@ bool TranslatorVisitor::arm_LDMIB(Cond cond, bool W, Reg n, RegList list) {
}
const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4));
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
return LDMHelper(ir, W, n, list, start_address, writeback_address);
}
@@ -896,7 +896,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, RegList list, IR::U32 s
// STM <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
@@ -905,13 +905,13 @@ bool TranslatorVisitor::arm_STM(Cond cond, bool W, Reg n, RegList list) {
}
const auto start_address = ir.GetRegister(n);
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(mcl::bit::count_ones(list) * 4)));
const auto writeback_address = ir.Add(start_address, ir.Imm32(u32(std::popcount(list) * 4)));
return STMHelper(ir, W, n, list, start_address, writeback_address);
}
// STMDA <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
@@ -919,14 +919,14 @@ bool TranslatorVisitor::arm_STMDA(Cond cond, bool W, Reg n, RegList list) {
return true;
}
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list) - 4)));
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list) - 4)));
const auto writeback_address = ir.Sub(start_address, ir.Imm32(4));
return STMHelper(ir, W, n, list, start_address, writeback_address);
}
// STMDB <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
@@ -934,14 +934,14 @@ bool TranslatorVisitor::arm_STMDB(Cond cond, bool W, Reg n, RegList list) {
return true;
}
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
const auto start_address = ir.Sub(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
const auto writeback_address = start_address;
return STMHelper(ir, W, n, list, start_address, writeback_address);
}
// STMIB <Rn>{!}, <reg_list>
bool TranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
if (n == Reg::PC || mcl::bit::count_ones(list) < 1) {
if (n == Reg::PC || std::popcount(list) < 1) {
return UnpredictableInstruction();
}
@@ -950,7 +950,7 @@ bool TranslatorVisitor::arm_STMIB(Cond cond, bool W, Reg n, RegList list) {
}
const auto start_address = ir.Add(ir.GetRegister(n), ir.Imm32(4));
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * mcl::bit::count_ones(list))));
const auto writeback_address = ir.Add(ir.GetRegister(n), ir.Imm32(u32(4 * std::popcount(list))));
return STMHelper(ir, W, n, list, start_address, writeback_address);
}
@@ -688,7 +688,7 @@ bool TranslatorVisitor::thumb16_NOP() {
// IT{<x>{<y>{<z>}}} <cond>
bool TranslatorVisitor::thumb16_IT(Imm<8> imm8) {
ASSERT((imm8.Bits<0, 3>() != 0b0000) && "Decode Error");
if (imm8.Bits<4, 7>() == 0b1111 || (imm8.Bits<4, 7>() == 0b1110 && mcl::bit::count_ones(imm8.Bits<0, 3>()) != 1)) {
if (imm8.Bits<4, 7>() == 0b1111 || (imm8.Bits<4, 7>() == 0b1110 && std::popcount(imm8.Bits<0, 3>()) != 1)) {
return UnpredictableInstruction();
}
if (ir.current_location.IT().IsInITBlock()) {
@@ -738,11 +738,11 @@ bool TranslatorVisitor::thumb16_PUSH(bool M, RegList reg_list) {
if (M) {
reg_list |= 1 << 14;
}
if (mcl::bit::count_ones(reg_list) < 1) {
if (std::popcount(reg_list) < 1) {
return UnpredictableInstruction();
}
const u32 num_bytes_to_push = static_cast<u32>(4 * mcl::bit::count_ones(reg_list));
const u32 num_bytes_to_push = static_cast<u32>(4 * std::popcount(reg_list));
const auto final_address = ir.Sub(ir.GetRegister(Reg::SP), ir.Imm32(num_bytes_to_push));
auto address = final_address;
for (size_t i = 0; i < 16; i++) {
@@ -764,7 +764,7 @@ bool TranslatorVisitor::thumb16_POP(bool P, RegList reg_list) {
if (P) {
reg_list |= 1 << 15;
}
if (mcl::bit::count_ones(reg_list) < 1) {
if (std::popcount(reg_list) < 1) {
return UnpredictableInstruction();
}
@@ -851,10 +851,10 @@ bool TranslatorVisitor::thumb16_BKPT(Imm<8> /*imm8*/) {
// STM <Rn>!, <reg_list>
bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
if (mcl::bit::count_ones(reg_list) == 0) {
if (std::popcount(reg_list) == 0) {
return UnpredictableInstruction();
}
if (mcl::bit::get_bit(static_cast<size_t>(n), reg_list) && n != static_cast<Reg>(mcl::bit::lowest_set_bit(reg_list))) {
if (mcl::bit::get_bit(static_cast<size_t>(n), reg_list) && n != static_cast<Reg>(std::countr_zero(reg_list))) {
return UnpredictableInstruction();
}
@@ -873,7 +873,7 @@ bool TranslatorVisitor::thumb16_STMIA(Reg n, RegList reg_list) {
// LDM <Rn>!, <reg_list>
bool TranslatorVisitor::thumb16_LDMIA(Reg n, RegList reg_list) {
if (mcl::bit::count_ones(reg_list) == 0) {
if (std::popcount(reg_list) == 0) {
return UnpredictableInstruction();
}
@@ -53,7 +53,7 @@ static bool STMHelper(A32::IREmitter& ir, bool W, Reg n, u32 list, const IR::U32
bool TranslatorVisitor::thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list) {
const auto regs_imm = reg_list.ZeroExtend();
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
if (n == Reg::PC || num_regs < 2) {
return UnpredictableInstruction();
@@ -78,7 +78,7 @@ bool TranslatorVisitor::thumb32_LDMDB(bool W, Reg n, Imm<16> reg_list) {
bool TranslatorVisitor::thumb32_LDMIA(bool W, Reg n, Imm<16> reg_list) {
const auto regs_imm = reg_list.ZeroExtend();
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
if (n == Reg::PC || num_regs < 2) {
return UnpredictableInstruction();
@@ -111,7 +111,7 @@ bool TranslatorVisitor::thumb32_PUSH(Imm<15> reg_list) {
bool TranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
const auto regs_imm = reg_list.ZeroExtend();
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
if (n == Reg::PC || num_regs < 2) {
return UnpredictableInstruction();
@@ -130,7 +130,7 @@ bool TranslatorVisitor::thumb32_STMIA(bool W, Reg n, Imm<15> reg_list) {
bool TranslatorVisitor::thumb32_STMDB(bool W, Reg n, Imm<15> reg_list) {
const auto regs_imm = reg_list.ZeroExtend();
const auto num_regs = static_cast<u32>(mcl::bit::count_ones(regs_imm));
const auto num_regs = static_cast<u32>(std::popcount(regs_imm));
if (n == Reg::PC || num_regs < 2) {
return UnpredictableInstruction();
@@ -55,7 +55,7 @@ std::optional<TranslatorVisitor::BitMasks> TranslatorVisitor::DecodeBitMasks(boo
const size_t esize = size_t{1} << len;
const u64 welem = mcl::bit::ones<u64>(S + 1);
const u64 telem = mcl::bit::ones<u64>(d + 1);
const u64 wmask = mcl::bit::rotate_right(mcl::bit::replicate_element<u64>(esize, welem), R);
const u64 wmask = std::rotr(mcl::bit::replicate_element<u64>(esize, welem), R);
const u64 tmask = mcl::bit::replicate_element<u64>(esize, telem);
return BitMasks{wmask, tmask};
@@ -13,7 +13,7 @@
namespace Dynarmic::A64 {
bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size > 3) {
return ReservedValue();
}
@@ -30,7 +30,7 @@ bool TranslatorVisitor::DUP_elt_1(Imm<5> imm5, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size > 3) {
return ReservedValue();
}
@@ -51,7 +51,7 @@ bool TranslatorVisitor::DUP_elt_2(bool Q, Imm<5> imm5, Vec Vn, Vec Vd) {
}
bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size > 3) {
return ReservedValue();
}
@@ -73,7 +73,7 @@ bool TranslatorVisitor::DUP_gen(bool Q, Imm<5> imm5, Reg Rn, Vec Vd) {
}
bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size == 2 && !Q) {
return UnallocatedEncoding();
}
@@ -96,7 +96,7 @@ bool TranslatorVisitor::SMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
}
bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size < 3 && Q) {
return UnallocatedEncoding();
}
@@ -123,7 +123,7 @@ bool TranslatorVisitor::UMOV(bool Q, Imm<5> imm5, Vec Vn, Reg Rd) {
}
bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size > 3) {
return ReservedValue();
}
@@ -140,7 +140,7 @@ bool TranslatorVisitor::INS_gen(Imm<5> imm5, Reg Rn, Vec Vd) {
}
bool TranslatorVisitor::INS_elt(Imm<5> imm5, Imm<4> imm4, Vec Vn, Vec Vd) {
const size_t size = mcl::bit::lowest_set_bit(imm5.ZeroExtend());
const size_t size = std::countr_zero(imm5.ZeroExtend());
if (size > 3) {
return ReservedValue();
}
+5 -5
View File
@@ -9,6 +9,7 @@
#include <algorithm>
#include <cstdio>
#include <map>
#include <bit>
#include <ankerl/unordered_dense.h>
#include "boost/container/small_vector.hpp"
@@ -28,7 +29,6 @@
#include "dynarmic/ir/opt_passes.h"
#include "dynarmic/ir/type.h"
#include "dynarmic/mcl/bit.hpp"
#include "dynarmic/mcl/bit.hpp"
namespace Dynarmic::Optimization {
@@ -1074,12 +1074,12 @@ static void ConstantPropagation(IR::Block& block) {
break;
case Op::BitRotateRight32:
if (FoldShifts(inst)) {
ReplaceUsesWith(inst, true, mcl::bit::rotate_right<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
ReplaceUsesWith(inst, true, std::rotr<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU8()));
}
break;
case Op::BitRotateRight64:
if (FoldShifts(inst)) {
ReplaceUsesWith(inst, false, mcl::bit::rotate_right<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
ReplaceUsesWith(inst, false, std::rotr<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU8()));
}
break;
case Op::LogicalShiftLeftMasked32:
@@ -1114,12 +1114,12 @@ static void ConstantPropagation(IR::Block& block) {
break;
case Op::RotateRightMasked32:
if (inst.AreAllArgsImmediates()) {
ReplaceUsesWith(inst, true, mcl::bit::rotate_right<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32()));
ReplaceUsesWith(inst, true, std::rotr<u32>(inst.GetArg(0).GetU32(), inst.GetArg(1).GetU32()));
}
break;
case Op::RotateRightMasked64:
if (inst.AreAllArgsImmediates()) {
ReplaceUsesWith(inst, false, mcl::bit::rotate_right<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64()));
ReplaceUsesWith(inst, false, std::rotr<u64>(inst.GetArg(0).GetU64(), inst.GetArg(1).GetU64()));
}
break;
case Op::Add32:
+34 -103
View File
@@ -8,26 +8,15 @@
#include <bitset>
#include <climits>
#include <cstddef>
#include <concepts>
#include <bit>
#include "common/common_types.h"
#include "common/assert.h"
namespace mcl {
namespace detail {
template<typename T, typename U>
concept SameHelper = std::is_same_v<T, U>;
} // namespace detail
template<typename T, typename U>
concept SameAs = detail::SameHelper<T, U> && detail::SameHelper<U, T>;
template<typename T, typename... U>
concept IsAnyOf = (SameAs<T, U> || ...);
/// Integral upon which bit operations can be safely performed.
template<typename T>
concept BitIntegral = IsAnyOf<T, u8, u16, u32, u64, std::uintptr_t, size_t>;
template<typename T>
constexpr std::size_t bitsizeof = CHAR_BIT * sizeof(T);
} // namespace mcl
namespace mcl::bit {
@@ -71,58 +60,37 @@ constexpr u64 swap_words_64(u64 value) {
| ((value & 0x00000000ffffffffull) << 32);
}
template<BitIntegral T>
constexpr T rotate_right(T x, size_t amount) {
amount %= bitsizeof<T>;
if (amount == 0) {
return x;
}
return static_cast<T>((x >> amount) | (x << (bitsizeof<T> - amount)));
}
template<BitIntegral T>
constexpr T rotate_left(T x, size_t amount) {
amount %= bitsizeof<T>;
if (amount == 0) {
return x;
}
return static_cast<T>((x << amount) | (x >> (bitsizeof<T> - amount)));
}
/// Create a mask with `count` number of one bits.
template<size_t count, BitIntegral T>
template<size_t count, std::integral T>
constexpr T ones() {
static_assert(count <= bitsizeof<T>, "count larger than bitsize of T");
if constexpr (count == 0) {
return 0;
} else {
return static_cast<T>(~static_cast<T>(0)) >> (bitsizeof<T> - count);
return T(~T(0)) >> (bitsizeof<T> - count);
}
}
/// Create a mask with `count` number of one bits.
template<BitIntegral T>
template<std::integral T>
constexpr T ones(size_t count) {
ASSERT(count <= bitsizeof<T> && "count larger than bitsize of T");
if (count == 0) {
if (count == 0)
return 0;
}
return static_cast<T>(~static_cast<T>(0)) >> (bitsizeof<T> - count);
return T(~T(0)) >> (bitsizeof<T> - count);
}
/// Create a mask of type T for bits [begin_bit, end_bit] inclusive.
template<size_t begin_bit, size_t end_bit, BitIntegral T>
template<size_t begin_bit, size_t end_bit, std::integral T>
constexpr T mask() {
static_assert(begin_bit <= end_bit, "invalid bit range (position of beginning bit cannot be greater than that of end bit)");
static_assert(begin_bit < bitsizeof<T>, "begin_bit must be smaller than size of T");
static_assert(end_bit < bitsizeof<T>, "end_bit must be smaller than size of T");
return ones<end_bit - begin_bit + 1, T>() << begin_bit;
}
/// Create a mask of type T for bits [begin_bit, end_bit] inclusive.
template<BitIntegral T>
template<std::integral T>
constexpr T mask(size_t begin_bit, size_t end_bit) {
ASSERT(begin_bit <= end_bit && "invalid bit range (position of beginning bit cannot be greater than that of end bit)");
ASSERT(begin_bit < bitsizeof<T> && "begin_bit must be smaller than size of T");
@@ -131,101 +99,100 @@ constexpr T mask(size_t begin_bit, size_t end_bit) {
}
/// Extract bits [begin_bit, end_bit] inclusive from value of type T.
template<size_t begin_bit, size_t end_bit, BitIntegral T>
template<size_t begin_bit, size_t end_bit, std::integral T>
constexpr T get_bits(T value) {
constexpr T m = mask<begin_bit, end_bit, T>();
return (value & m) >> begin_bit;
}
/// Extract bits [begin_bit, end_bit] inclusive from value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T get_bits(size_t begin_bit, size_t end_bit, T value) {
const T m = mask<T>(begin_bit, end_bit);
return (value & m) >> begin_bit;
}
/// Clears bits [begin_bit, end_bit] inclusive of value of type T.
template<size_t begin_bit, size_t end_bit, BitIntegral T>
template<size_t begin_bit, size_t end_bit, std::integral T>
constexpr T clear_bits(T value) {
constexpr T m = mask<begin_bit, end_bit, T>();
return value & ~m;
}
/// Clears bits [begin_bit, end_bit] inclusive of value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T clear_bits(size_t begin_bit, size_t end_bit, T value) {
const T m = mask<T>(begin_bit, end_bit);
return value & ~m;
}
/// Modifies bits [begin_bit, end_bit] inclusive of value of type T.
template<size_t begin_bit, size_t end_bit, BitIntegral T>
template<size_t begin_bit, size_t end_bit, std::integral T>
constexpr T set_bits(T value, T new_bits) {
constexpr T m = mask<begin_bit, end_bit, T>();
return (value & ~m) | ((new_bits << begin_bit) & m);
}
/// Modifies bits [begin_bit, end_bit] inclusive of value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T set_bits(size_t begin_bit, size_t end_bit, T value, T new_bits) {
const T m = mask<T>(begin_bit, end_bit);
return (value & ~m) | ((new_bits << begin_bit) & m);
}
/// Extract bit at bit_position from value of type T.
template<size_t bit_position, BitIntegral T>
template<size_t bit_position, std::integral T>
constexpr bool get_bit(T value) {
constexpr T m = mask<bit_position, bit_position, T>();
return (value & m) != 0;
}
/// Extract bit at bit_position from value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr bool get_bit(size_t bit_position, T value) {
const T m = mask<T>(bit_position, bit_position);
return (value & m) != 0;
}
/// Clears bit at bit_position of value of type T.
template<size_t bit_position, BitIntegral T>
template<size_t bit_position, std::integral T>
constexpr T clear_bit(T value) {
constexpr T m = mask<bit_position, bit_position, T>();
return value & ~m;
}
/// Clears bit at bit_position of value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T clear_bit(size_t bit_position, T value) {
const T m = mask<T>(bit_position, bit_position);
return value & ~m;
}
/// Modifies bit at bit_position of value of type T.
template<size_t bit_position, BitIntegral T>
template<size_t bit_position, std::integral T>
constexpr T set_bit(T value, bool new_bit) {
constexpr T m = mask<bit_position, bit_position, T>();
return (value & ~m) | (new_bit ? m : static_cast<T>(0));
return (value & ~m) | (new_bit ? m : T(0));
}
/// Modifies bit at bit_position of value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T set_bit(size_t bit_position, T value, bool new_bit) {
const T m = mask<T>(bit_position, bit_position);
return (value & ~m) | (new_bit ? m : static_cast<T>(0));
return (value & ~m) | (new_bit ? m : T(0));
}
/// Sign-extends a value that has bit_count bits to the full bitwidth of type T.
template<size_t bit_count, BitIntegral T>
template<size_t bit_count, std::integral T>
constexpr T sign_extend(T value) {
static_assert(bit_count != 0, "cannot sign-extend zero-sized value");
using S = std::make_signed_t<T>;
constexpr size_t shift_amount = bitsizeof<T> - bit_count;
return static_cast<T>(static_cast<S>(value << shift_amount) >> shift_amount);
return T(S(value << shift_amount) >> shift_amount);
}
/// Sign-extends a value that has bit_count bits to the full bitwidth of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T sign_extend(size_t bit_count, T value) {
ASSERT(bit_count != 0 && "cannot sign-extend zero-sized value");
using S = std::make_signed_t<T>;
@@ -234,78 +201,42 @@ constexpr T sign_extend(size_t bit_count, T value) {
}
/// Replicate an element across a value of type T.
template<size_t element_size, BitIntegral T>
template<size_t element_size, std::integral T>
constexpr T replicate_element(T value) {
static_assert(element_size <= bitsizeof<T>, "element_size is too large");
static_assert(bitsizeof<T> % element_size == 0, "bitsize of T not divisible by element_size");
if constexpr (element_size == bitsizeof<T>) {
return value;
} else {
return replicate_element<element_size * 2, T>(static_cast<T>(value | (value << element_size)));
return replicate_element<element_size * 2, T>(T(value | (value << element_size)));
}
}
/// Replicate an element of type U across a value of type T.
template<BitIntegral U, BitIntegral T>
template<std::integral U, std::integral T>
constexpr T replicate_element(T value) {
static_assert(bitsizeof<U> <= bitsizeof<T>, "element_size is too large");
return replicate_element<bitsizeof<U>, T>(value);
}
/// Replicate an element across a value of type T.
template<BitIntegral T>
template<std::integral T>
constexpr T replicate_element(size_t element_size, T value) {
ASSERT(element_size <= bitsizeof<T> && "element_size is too large");
ASSERT(bitsizeof<T> % element_size == 0 && "bitsize of T not divisible by element_size");
if (element_size == bitsizeof<T>)
return value;
return replicate_element<T>(element_size * 2, static_cast<T>(value | (value << element_size)));
return replicate_element<T>(element_size * 2, T(value | (value << element_size)));
}
template<BitIntegral T>
template<std::integral T>
constexpr bool most_significant_bit(T value) {
return get_bit<bitsizeof<T> - 1, T>(value);
}
template<BitIntegral T>
inline size_t count_ones(T x) {
return std::bitset<bitsizeof<T>>(x).count();
}
template<BitIntegral T>
constexpr size_t count_leading_zeros(T x) {
size_t result = bitsizeof<T>;
while (x != 0) {
x >>= 1;
result--;
}
return result;
}
template<BitIntegral T>
template<std::integral T>
constexpr int highest_set_bit(T x) {
int result = -1;
while (x != 0) {
x >>= 1;
result++;
}
return result;
}
template<BitIntegral T>
constexpr size_t lowest_set_bit(T x) {
if (x == 0) {
return bitsizeof<T>;
}
size_t result = 0;
while ((x & 1) == 0) {
x >>= 1;
result++;
}
return result;
return std::bit_width(x) - 1;
}
} // namespace mcl::bit
@@ -17,25 +17,25 @@ struct integer_of_size_impl {};
template<>
struct integer_of_size_impl<8> {
using unsigned_type = u8;
using signed_type = s8;
using signed_type = std::make_signed_t<unsigned_type>;
};
template<>
struct integer_of_size_impl<16> {
using unsigned_type = u16;
using signed_type = s16;
using signed_type = std::make_signed_t<unsigned_type>;
};
template<>
struct integer_of_size_impl<32> {
using unsigned_type = u32;
using signed_type = s32;
using signed_type = std::make_signed_t<unsigned_type>;
};
template<>
struct integer_of_size_impl<64> {
using unsigned_type = u64;
using signed_type = s64;
using signed_type = std::make_signed_t<unsigned_type>;
};
} // namespace detail
@@ -10,23 +10,12 @@
namespace mcl {
/// A metavalue (of type VT and value v).
template<class VT, VT v> using value = std::integral_constant<VT, v>;
/// A metavalue of type size_t (and value v).
template<size_t v> using size_value = value<size_t, v>;
/// A metavalue of type bool (and value v). (Aliases to std::bool_constant.)
template<bool v> using bool_value = value<bool, v>;
/// true metavalue (Aliases to std::true_type).
using true_type = bool_value<true>;
/// false metavalue (Aliases to std::false_type).
using false_type = bool_value<false>;
/// Is type T an instance of template class C?
template<template<class...> class, class>
struct is_instance_of_template : false_type {};
struct is_instance_of_template : std::false_type {};
template<template<class...> class C, class... As>
struct is_instance_of_template<C, C<As...>> : true_type {};
struct is_instance_of_template<C, C<As...>> : std::true_type {};
/// Is type T an instance of template class C?
template<template<class...> class C, class T>
+1 -1
View File
@@ -665,7 +665,7 @@ TEST_CASE("A32: Test thumb IT instruction", "[thumb]") {
A32::ITState it_state = [&] {
while (true) {
const u16 imm8 = RandInt<u16>(0, 0xFF);
if (mcl::bit::get_bits<0, 3>(imm8) == 0b0000 || mcl::bit::get_bits<4, 7>(imm8) == 0b1111 || (mcl::bit::get_bits<4, 7>(imm8) == 0b1110 && mcl::bit::count_ones(mcl::bit::get_bits<0, 3>(imm8)) != 1)) {
if (mcl::bit::get_bits<0, 3>(imm8) == 0b0000 || mcl::bit::get_bits<4, 7>(imm8) == 0b1111 || (mcl::bit::get_bits<4, 7>(imm8) == 0b1110 && std::popcount(mcl::bit::get_bits<0, 3>(imm8)) != 1)) {
continue;
}
instructions.push_back(0b1011111100000000 | imm8);
-1
View File
@@ -3,7 +3,6 @@
#include <algorithm>
#include <filesystem>
#include <iostream>
#include <fmt/format.h>
#include "common/fs/fs.h"
#include "common/fs/fs_types.h"
+4
View File
@@ -31,6 +31,10 @@ add_library(qt_common STATIC
abstract/frontend.h abstract/frontend.cpp
abstract/progress.h abstract/progress.cpp
game_list/model.h game_list/model.cpp
game_list/worker.h game_list/worker.cpp
game_list/game_list_p.h
qt_string_lookup.h
qt_compat.h
@@ -17,14 +17,13 @@
#include <QRegularExpression>
#include <QStandardItem>
#include <QString>
#include <QWidget>
#include "common/common_types.h"
#include "common/logging.h"
#include "common/string_util.h"
#include "frontend_common/play_time_manager.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/util/util.h"
#include "qt_common/qt_common.h"
enum class GameListItemType {
Game = QStandardItem::UserType + 1,
@@ -204,7 +203,7 @@ public:
setData(compatibility, CompatNumberRole);
setText(tr(status.text));
setToolTip(tr(status.tooltip));
setData(CreateCirclePixmapFromColor(status.color), Qt::DecorationRole);
setData(QtCommon::CreateCirclePixmapFromColor(status.color), Qt::DecorationRole);
}
int type() const override {
@@ -237,7 +236,7 @@ public:
// representations of the data are always accurate and in the correct format.
if (role == SizeRole) {
qulonglong size_bytes = value.toULongLong();
GameListItem::setData(ReadableByteSize(size_bytes), Qt::DisplayRole);
GameListItem::setData(QtCommon::ReadableByteSize(size_bytes), Qt::DisplayRole);
GameListItem::setData(value, SizeRole);
} else {
GameListItem::setData(value, role);
@@ -398,49 +397,3 @@ public:
return false;
}
};
class GameList;
class QHBoxLayout;
class QTreeView;
class QLabel;
class QLineEdit;
class QToolButton;
class GameListSearchField : public QWidget {
Q_OBJECT
public:
explicit GameListSearchField(GameList* parent = nullptr);
QString filterText() const;
void setFilterResult(int visible_, int total_);
void clear();
void setFocus();
private:
void changeEvent(QEvent*) override;
void RetranslateUI();
class KeyReleaseEater : public QObject {
public:
explicit KeyReleaseEater(GameList* gamelist_, QObject* parent = nullptr);
private:
GameList* gamelist = nullptr;
QString edit_filter_text_old;
protected:
// EventFilter in order to process systemkeys while editing the searchfield
bool eventFilter(QObject* obj, QEvent* event) override;
};
int visible;
int total;
QHBoxLayout* layout_filter = nullptr;
QTreeView* tree_view = nullptr;
QLabel* label_filter = nullptr;
QLineEdit* edit_filter = nullptr;
QLabel* label_filter_result = nullptr;
QToolButton* button_filter_close = nullptr;
};
+303
View File
@@ -0,0 +1,303 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include <QDir>
#include <QIcon>
#include <QJsonArray>
#include <QJsonDocument>
#include <QJsonObject>
#include <QThreadPool>
#include "common/logging.h"
#include "common/settings.h"
#include "core/core.h"
#include "core/file_sys/patch_manager.h"
#include "core/file_sys/registered_cache.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "qt_common/config/uisettings.h"
#include "qt_common/qt_common.h"
#include "qt_common/util/game.h"
#include "qt_common/game_list/game_list_p.h"
#include "qt_common/game_list/worker.h"
#include "qt_common/game_list/model.h"
GameListModel::GameListModel(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
FileSys::ManualContentProvider* provider_,
const PlayTime::PlayTimeManager& play_time_manager_,
Core::System& system_, QObject* parent)
: QStandardItemModel{parent}, vfs{std::move(vfs_)}, provider{provider_},
play_time_manager{play_time_manager_}, system{system_} {
watcher = new QFileSystemWatcher(this);
external_watcher = new QFileSystemWatcher(this);
connect(watcher, &QFileSystemWatcher::directoryChanged, this,
&GameListModel::RefreshGameDirectory);
connect(external_watcher, &QFileSystemWatcher::directoryChanged, this,
&GameListModel::RefreshExternalContent);
insertColumns(0, COLUMN_COUNT);
RetranslateUI();
setSortRole(GameListItemPath::SortRole);
}
GameListModel::~GameListModel() = default;
void GameListModel::PopulateAsync(QVector<UISettings::GameDir>& game_dirs) {
current_worker.reset();
removeRows(0, rowCount());
current_worker = std::make_unique<GameListWorker>(vfs, provider, game_dirs, compatibility_list,
play_time_manager, system);
connect(current_worker.get(), &GameListWorker::DataAvailable, this, &GameListModel::WorkerEvent,
Qt::QueuedConnection);
QThreadPool::globalInstance()->start(current_worker.get());
}
void GameListModel::WorkerEvent() {
current_worker->ProcessEvents(this);
}
void GameListModel::AddDirEntry(GameListDir* entry_items) {
if (m_flat) {
return;
}
invisibleRootItem()->appendRow(entry_items);
}
void GameListModel::AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent) {
if (m_flat) {
invisibleRootItem()->appendRow(entry_items);
} else {
parent->appendRow(entry_items);
}
}
void GameListModel::DonePopulating(const QStringList& watch_list) {
emit ShowList(!IsEmpty());
if (!m_flat) {
invisibleRootItem()->appendRow(new GameListAddDir());
invisibleRootItem()->insertRow(0, new GameListFavorites());
for (const auto id : std::as_const(UISettings::values.favorited_ids)) {
AddFavorite(id);
}
}
emit PopulatingCompleted(watch_list);
}
bool GameListModel::IsEmpty() const {
for (int i = 0; i < rowCount(); i++) {
const QStandardItem* child = invisibleRootItem()->child(i);
const auto type = static_cast<GameListItemType>(child->type());
if (!child->hasChildren() &&
(type == GameListItemType::SdmcDir || type == GameListItemType::UserNandDir ||
type == GameListItemType::SysNandDir)) {
invisibleRootItem()->removeRow(child->row());
i--;
}
}
return !invisibleRootItem()->hasChildren();
}
void GameListModel::ToggleFavorite(u64 program_id) {
if (!UISettings::values.favorited_ids.contains(program_id)) {
UISettings::values.favorited_ids.append(program_id);
AddFavorite(program_id);
} else {
UISettings::values.favorited_ids.removeOne(program_id);
RemoveFavorite(program_id);
}
emit SaveConfig();
}
void GameListModel::AddFavorite(u64 program_id) {
auto* favorites_row = item(0);
for (int i = 1; i < rowCount() - 1; i++) {
const auto* folder = item(i);
for (int j = 0; j < folder->rowCount(); j++) {
if (folder->child(j)->data(GameListItemPath::ProgramIdRole).toULongLong() ==
program_id) {
QList<QStandardItem*> list;
for (int k = 0; k < COLUMN_COUNT; k++) {
list.append(folder->child(j, k)->clone());
}
list[0]->setData(folder->child(j)->data(GameListItem::SortRole),
GameListItem::SortRole);
list[0]->setText(folder->child(j)->data(Qt::DisplayRole).toString());
favorites_row->appendRow(list);
return;
}
}
}
}
void GameListModel::RemoveFavorite(u64 program_id) {
auto* favorites_row = item(0);
for (int i = 0; i < favorites_row->rowCount(); i++) {
const auto* game = favorites_row->child(i);
if (game->data(GameListItemPath::ProgramIdRole).toULongLong() == program_id) {
favorites_row->removeRow(i);
return;
}
}
}
void GameListModel::LoadCompatibilityList() {
QFile compat_list{QStringLiteral(":compatibility_list/compatibility_list.json")};
if (!compat_list.open(QFile::ReadOnly | QFile::Text)) {
LOG_ERROR(Frontend, "Unable to open game compatibility list");
return;
}
if (compat_list.size() == 0) {
LOG_WARNING(Frontend, "Game compatibility list is empty");
return;
}
const QByteArray content = compat_list.readAll();
if (content.isEmpty()) {
LOG_ERROR(Frontend, "Unable to completely read game compatibility list");
return;
}
const QJsonDocument json = QJsonDocument::fromJson(content);
const QJsonArray arr = json.array();
for (const QJsonValue& value : arr) {
const QJsonObject game = value.toObject();
const QString compatibility_key = QStringLiteral("compatibility");
if (!game.contains(compatibility_key) || !game[compatibility_key].isDouble()) {
continue;
}
const int compatibility = game[compatibility_key].toInt();
const QString directory = game[QStringLiteral("directory")].toString();
const QJsonArray ids = game[QStringLiteral("releases")].toArray();
for (const QJsonValue& id_ref : ids) {
const QJsonObject id_object = id_ref.toObject();
const QString id = id_object[QStringLiteral("id")].toString();
compatibility_list.emplace(id.toUpper().toStdString(),
std::make_pair(QString::number(compatibility), directory));
}
}
}
void GameListModel::RefreshGameDirectory() {
ResetExternalWatcher();
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
LOG_INFO(Frontend, "Change detected in the games directory. Reloading game list.");
QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
PopulateAsync(UISettings::values.game_dirs);
}
}
void GameListModel::RefreshExternalContent() {
if (!UISettings::values.game_dirs.empty() && current_worker != nullptr) {
LOG_INFO(Frontend, "External content directory changed. Clearing metadata cache.");
QtCommon::Game::ResetMetadata(false);
QtCommon::system->GetFileSystemController().CreateFactories(*QtCommon::vfs);
PopulateAsync(UISettings::values.game_dirs);
}
}
void GameListModel::ResetExternalWatcher() {
auto watch_dirs = external_watcher->directories();
if (!watch_dirs.isEmpty()) {
external_watcher->removePaths(watch_dirs);
}
for (const std::string& dir : Settings::values.external_content_dirs) {
external_watcher->addPath(QString::fromStdString(dir));
}
}
void GameListModel::OnUpdateThemedIcons() {
for (int i = 0; i < invisibleRootItem()->rowCount(); i++) {
QStandardItem* child = invisibleRootItem()->child(i);
const int icon_size = UISettings::values.folder_icon_size.GetValue();
switch (child->data(GameListItem::TypeRole).value<GameListItemType>()) {
case GameListItemType::SdmcDir:
child->setData(
QIcon::fromTheme(QStringLiteral("sd_card"))
.pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
break;
case GameListItemType::UserNandDir:
case GameListItemType::SysNandDir:
child->setData(
QIcon::fromTheme(QStringLiteral("chip"))
.pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
break;
case GameListItemType::CustomDir: {
const UISettings::GameDir& game_dir =
UISettings::values.game_dirs[child->data(GameListDir::GameDirRole).toInt()];
const QString icon_name = QFileInfo::exists(QString::fromStdString(game_dir.path))
? QStringLiteral("folder")
: QStringLiteral("bad_folder");
child->setData(
QIcon::fromTheme(icon_name).pixmap(icon_size).scaled(
icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
break;
}
case GameListItemType::AddDir:
child->setData(
QIcon::fromTheme(QStringLiteral("list-add"))
.pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
break;
case GameListItemType::Favorites:
child->setData(
QIcon::fromTheme(QStringLiteral("star"))
.pixmap(icon_size)
.scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation),
Qt::DecorationRole);
break;
default:
break;
}
}
}
void GameListModel::RetranslateUI() {
setHeaderData(COLUMN_NAME, Qt::Horizontal, tr("Name"));
setHeaderData(COLUMN_COMPATIBILITY, Qt::Horizontal, tr("Compatibility"));
setHeaderData(COLUMN_ADD_ONS, Qt::Horizontal, tr("Add-ons"));
setHeaderData(COLUMN_FILE_TYPE, Qt::Horizontal, tr("File type"));
setHeaderData(COLUMN_SIZE, Qt::Horizontal, tr("Size"));
setHeaderData(COLUMN_PLAY_TIME, Qt::Horizontal, tr("Play time"));
}
QFileSystemWatcher* GameListModel::GetWatcher() const {
return watcher;
}
const CompatibilityList& GameListModel::GetCompatibilityList() const {
return compatibility_list;
}
void GameListModel::SetFlat(bool flat) {
m_flat = flat;
}
+98
View File
@@ -0,0 +1,98 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QFileSystemWatcher>
#include <QStandardItemModel>
#include <QStringList>
#include <QVector>
#include <memory>
#include "common/common_types.h"
#include "frontend_common/play_time_manager.h"
#include "qt_common/config/uisettings.h"
#include "yuzu/compatibility_list.h"
namespace Core {
class System;
}
class GameListDir;
class GameListWorker;
class QStandardItem;
namespace FileSys {
class ManualContentProvider;
class VfsFilesystem;
} // namespace FileSys
class GameListModel : public QStandardItemModel {
Q_OBJECT
public:
enum Column {
COLUMN_NAME,
COLUMN_FILE_TYPE,
COLUMN_SIZE,
COLUMN_PLAY_TIME,
COLUMN_ADD_ONS,
COLUMN_COMPATIBILITY,
COLUMN_COUNT,
};
explicit GameListModel(std::shared_ptr<FileSys::VfsFilesystem> vfs_,
FileSys::ManualContentProvider* provider_,
const PlayTime::PlayTimeManager& play_time_manager_,
Core::System& system_, QObject* parent = nullptr);
~GameListModel() override;
void AddDirEntry(GameListDir* entry_items);
void AddEntry(const QList<QStandardItem*>& entry_items, GameListDir* parent);
void DonePopulating(const QStringList& watch_list);
void PopulateAsync(QVector<UISettings::GameDir>& game_dirs);
void WorkerEvent();
bool IsEmpty() const;
void ToggleFavorite(u64 program_id);
void RefreshGameDirectory();
void RefreshExternalContent();
void ResetExternalWatcher();
void LoadCompatibilityList();
void OnUpdateThemedIcons();
void RetranslateUI();
QFileSystemWatcher* GetWatcher() const;
const CompatibilityList& GetCompatibilityList() const;
void SetFlat(bool flat);
signals:
void ShowList(bool show);
void PopulatingCompleted(const QStringList& watch_list);
void SaveConfig();
private:
friend class GameListWorker;
void AddFavorite(u64 program_id);
void RemoveFavorite(u64 program_id);
bool m_flat = false;
std::shared_ptr<FileSys::VfsFilesystem> vfs;
FileSys::ManualContentProvider* provider;
CompatibilityList compatibility_list;
const PlayTime::PlayTimeManager& play_time_manager;
Core::System& system;
std::unique_ptr<GameListWorker> current_worker;
QFileSystemWatcher* watcher = nullptr;
QFileSystemWatcher* external_watcher = nullptr;
};
@@ -33,9 +33,10 @@
#include "qt_common/qt_common.h"
#include "yuzu/compatibility_list.h"
#include "yuzu/game/game_list.h"
#include "yuzu/game/game_list_p.h"
#include "yuzu/game/game_list_worker.h"
#include "qt_common/game_list/game_list_p.h"
#include "qt_common/game_list/worker.h"
#include "qt_common/game_list/model.h"
namespace {
@@ -250,9 +251,9 @@ GameListWorker::~GameListWorker() {
processing_completed.Wait();
}
void GameListWorker::ProcessEvents(GameList* game_list) {
void GameListWorker::ProcessEvents(GameListModel* model) {
while (true) {
std::function<void(GameList*)> func;
std::function<void(GameListModel*)> func;
{
// Lock queue to protect concurrent modification.
std::scoped_lock lk(lock);
@@ -268,7 +269,7 @@ void GameListWorker::ProcessEvents(GameList* game_list) {
}
// Run the function.
func(game_list);
func(model);
}
}
@@ -335,7 +336,7 @@ void GameListWorker::AddTitlesToGameList(GameListDir* parent_dir) {
auto entry = MakeGameListEntry(file->GetFullPath(), name, file->GetSize(), icon, *loader,
program_id, compatibility_list, play_time_manager, patch);
RecordEvent([=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
RecordEvent([=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
}
}
@@ -417,7 +418,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
}
} else {
std::vector<u8> icon;
@@ -434,7 +435,7 @@ void GameListWorker::ScanFileSystem(ScanTarget target, const std::string& dir_pa
program_id, compatibility_list, play_time_manager, patch);
RecordEvent(
[=](GameList* game_list) { game_list->AddEntry(entry, parent_dir); });
[=](GameListModel* model) { model->AddEntry(entry, parent_dir); });
}
}
} else if (is_dir) {
@@ -457,7 +458,7 @@ void GameListWorker::run() {
provider->ClearAllEntries();
const auto DirEntryReady = [&](GameListDir* game_list_dir) {
RecordEvent([=](GameList* game_list) { game_list->AddDirEntry(game_list_dir); });
RecordEvent([=](GameListModel* model) { model->AddDirEntry(game_list_dir); });
};
for (UISettings::GameDir& game_dir : game_dirs) {
@@ -491,6 +492,6 @@ void GameListWorker::run() {
}
}
RecordEvent([this](GameList* game_list) { game_list->DonePopulating(watch_list); });
RecordEvent([this](GameListModel* model) { model->DonePopulating(watch_list); });
processing_completed.Set();
}
@@ -26,8 +26,8 @@ namespace Core {
class System;
}
class GameList;
class GameListDir;
class GameListModel;
class QStandardItem;
namespace FileSys {
@@ -58,11 +58,11 @@ public:
/**
* Synchronously processes any events queued by the worker.
*
* AddDirEntry is called on the game list for every discovered directory.
* AddEntry is called on the game list for every discovered program.
* DonePopulating is called on the game list when processing completes.
* AddDirEntry is called on the model for every discovered directory.
* AddEntry is called on the model for every discovered program.
* DonePopulating is called on the model when processing completes.
*/
void ProcessEvents(GameList* game_list);
void ProcessEvents(GameListModel* model);
signals:
void DataAvailable();
@@ -92,7 +92,7 @@ private:
std::mutex lock;
std::condition_variable cv;
std::deque<std::function<void(GameList*)>> queued_events;
std::deque<std::function<void(GameListModel*)>> queued_events;
std::atomic_bool stop_requested = false;
Common::Event processing_completed;
+17
View File
@@ -5,6 +5,7 @@
#include "common/memory_detect.h"
#include "core/hle/service/filesystem/filesystem.h"
#include "frontend_common/data_manager.h"
#include "hid_core/hid_core.h"
#include "network/network.h"
#include "qt_common.h"
@@ -27,6 +28,7 @@
#include <thread>
#include <JlCompress.h>
#include <QPainter>
#if !defined(WIN32) && !defined(__APPLE__)
#include <qpa/qplatformnativeinterface.h>
@@ -307,4 +309,19 @@ void SetupHID() {
system->HIDCore().ReloadInputDevices();
}
QString ReadableByteSize(qulonglong size) {
return QString::fromStdString(FrontendCommon::DataManager::ReadableBytesSize(size));
}
QPixmap CreateCirclePixmapFromColor(const QColor& color) {
QPixmap circle_pixmap(16, 16);
circle_pixmap.fill(Qt::transparent);
QPainter painter(&circle_pixmap);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(color);
painter.setBrush(color);
painter.drawEllipse({circle_pixmap.width() / 2.0, circle_pixmap.height() / 2.0}, 7.0, 7.0);
return circle_pixmap;
}
} // namespace QtCommon
+14
View File
@@ -46,6 +46,20 @@ void SetupHID();
const QString tr(const char* str);
const QString tr(const std::string& str);
// TODO: Find a better place for these
/// Convert a size in bytes into a readable format (KiB, MiB, etc.)
[[nodiscard]] QString ReadableByteSize(qulonglong size);
/**
* Creates a circle pixmap from a specified color
* @param color The color the pixmap shall have
* @return QPixmap circle pixmap
*/
[[nodiscard]] QPixmap CreateCirclePixmapFromColor(const QColor& color);
std::filesystem::path GetEdenCommand();
} // namespace QtCommon
#endif
+6 -3
View File
@@ -33,10 +33,13 @@ QStringList GetModFolders(const QString& root, const QString& fallbackName) {
std_path = paths[0];
QString default_name;
if (!fallbackName.isEmpty())
default_name = fallbackName;
else if (!paths.empty())
// If this is an atmosphere-packed mod, the default name will end up as the game's title ID.
// So in this case ignore it and use the zip name instead
if (!paths.empty() && std_path.string().find("atmosphere") == std::string::npos)
default_name = QString::fromStdString(std_path.filename().string());
else if (!fallbackName.isEmpty())
default_name = fallbackName;
else
default_name = root.split(QLatin1Char('/')).last();
@@ -12,6 +12,7 @@
#include <limits>
#include <boost/container/small_vector.hpp>
#include "common/settings.h"
#include "shader_recompiler/environment.h"
#include "shader_recompiler/frontend/ir/basic_block.h"
#include "shader_recompiler/frontend/ir/breadth_first_search.h"
@@ -820,8 +821,7 @@ void TexturePass(Environment& env, IR::Program& program, const HostTranslateInfo
const auto insert_point{IR::Block::InstructionList::s_iterator_to(*inst)};
IR::IREmitter ir{*texture_inst.block, insert_point};
const IR::U32 shift{ir.Imm32(size_shift)};
inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift),
ir.Imm32(count - 1)));
inst->SetArg(0, ir.UMin(ir.ShiftRightLogical(cbuf.dynamic_offset, shift), ir.Imm32(count - 1)));
} else {
inst->SetArg(0, IR::Value{});
}
+9 -15
View File
@@ -1893,23 +1893,17 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
return NULL_BINDING;
}
// xbzk: New size logic. Fixes MCI.
// If ever the * comment below prove wrong, the 'if' block may be removed.
const auto size = [&]() {
const bool is_nvn_cbuf = cbuf_index == 0;
if (is_nvn_cbuf) {
// * The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
const u32 upper_32 = static_cast<u32>(next_qword >> 32);
// Hardware-based detection: GPU addresses have non-zero upper bits
if (upper_32 == 0) {
// This is a size field, not a GPU address
return static_cast<u32>(next_qword); // Return lower_32
}
const u32 memory_layout_size =
static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
const u64 next_qword = gpu_memory->Read<u64>(ssbo_addr + 8);
const u32 packed_size = static_cast<u32>(next_qword);
const bool next_qword_is_size = static_cast<u32>(next_qword >> 32) == 0 &&
packed_size != 0 &&
packed_size <= memory_layout_size;
if (next_qword_is_size) {
return packed_size;
}
// Fall through: either not NVN cbuf (Doom Eternal & +), or NVN but ssbo_addr+8 is a GPU address (MCI)
const u32 memory_layout_size = static_cast<u32>(gpu_memory->GetMemoryLayoutSize(gpu_addr));
// Cap at 8MB to prevent allocator overflow from misinterpreted addresses
return (std::min)(memory_layout_size, static_cast<u32>(8_MiB));
}();
@@ -436,7 +436,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
.layerCount = 1,
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, barrier);
}
@@ -69,7 +69,7 @@ void TransitionImageLayout(vk::CommandBuffer& cmdbuf, VkImage image, VkImageLayo
.layerCount = 1,
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, barrier);
}
@@ -171,10 +171,10 @@ void DownloadColorImage(vk::CommandBuffer& cmdbuf, VkImage image, VkBuffer buffe
.imageOffset{.x = 0, .y = 0, .z = 0},
.imageExtent{extent},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
read_barrier);
cmdbuf.CopyImageToBuffer(image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, buffer, copy);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0,
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0,
memory_write_barrier, nullptr, image_write_barrier);
}
@@ -8,7 +8,6 @@
#include <array>
#include <cstring>
#include <memory>
#include <mutex>
#include <optional>
#include <string>
#include <vector>
@@ -172,11 +171,7 @@ try
RendererVulkan::~RendererVulkan() {
scheduler.RegisterOnSubmit([] {});
scheduler.Finish();
{
std::scoped_lock lock{scheduler.submit_mutex};
void(device.GetLogical().WaitIdle());
}
void(device.GetLogical().WaitIdle());
}
void RendererVulkan::Composite(std::span<const Tegra::FramebufferConfig> framebuffers) {
@@ -8,7 +8,6 @@
// SPDX-License-Identifier: GPL-2.0-or-later
#include <vulkan/vulkan_core.h>
#include <mutex>
#include "video_core/framebuffer_config.h"
#include "video_core/present.h"
#include "video_core/renderer_vulkan/present/filters.h"
@@ -32,10 +31,7 @@ BlitScreen::~BlitScreen() = default;
void BlitScreen::WaitIdle() {
present_manager.WaitPresent();
scheduler.Finish();
{
std::scoped_lock lock{scheduler.submit_mutex};
device.GetLogical().WaitIdle();
}
device.GetLogical().WaitIdle();
}
void BlitScreen::SetWindowAdaptPass() {
@@ -437,13 +437,13 @@ void BufferCacheRuntime::CopyBuffer(VkBuffer dst_buffer, VkBuffer src_buffer,
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([src_buffer, dst_buffer, vk_copies, barrier](vk::CommandBuffer cmdbuf) {
if (barrier) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_PIPELINE_STAGE_TRANSFER_BIT, 0, READ_BARRIER);
}
cmdbuf.CopyBuffer(src_buffer, dst_buffer, VideoCommon::FixSmallVectorADL(vk_copies));
if (barrier) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, WRITE_BARRIER);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, WRITE_BARRIER);
}
});
}
@@ -457,7 +457,7 @@ void BufferCacheRuntime::PreCopyBarrier() {
};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, READ_BARRIER);
});
}
@@ -471,7 +471,7 @@ void BufferCacheRuntime::PostCopyBarrier() {
};
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, WRITE_BARRIER);
});
}
@@ -495,10 +495,10 @@ void BufferCacheRuntime::ClearBuffer(VkBuffer dest_buffer, u32 offset, size_t si
scheduler.RequestOutsideRenderPassOperationContext();
scheduler.Record([dest_buffer, offset, size, value](vk::CommandBuffer cmdbuf) {
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER, VK_PIPELINE_STAGE_TRANSFER_BIT,
0, READ_BARRIER);
cmdbuf.FillBuffer(dest_buffer, offset, size, value);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, vk::PIPELINE_STAGE_GRAPHICS_COMPUTE,
0, WRITE_BARRIER);
});
}
@@ -454,8 +454,8 @@ void ConditionalRenderingResolvePass::Resolve(VkBuffer dst_buffer, VkBuffer src_
const VkDescriptorSet set = descriptor_allocator.Commit();
device.GetLogical().UpdateDescriptorSet(set, *descriptor_template, descriptor_data);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.PipelineBarrier(vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, read_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
cmdbuf.BindDescriptorSets(VK_PIPELINE_BIND_POINT_COMPUTE, *layout, 0, set, {});
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
@@ -537,7 +537,7 @@ void QueriesPrefixScanPass::Run(VkBuffer accumulation_buffer, VkBuffer dst_buffe
cmdbuf.PushConstants(*layout, VK_SHADER_STAGE_COMPUTE_BIT, uniforms);
cmdbuf.Dispatch(1, 1, 1);
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, write_barrier);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, write_barrier);
});
}
}
@@ -589,9 +589,9 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
.layerCount = VK_REMAINING_ARRAY_LAYERS,
},
};
cmdbuf.PipelineBarrier(is_initialized ? VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
: VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
cmdbuf.PipelineBarrier(is_initialized ? vk::PIPELINE_STAGE_GRAPHICS_COMPUTE_TRANSFER
: VkPipelineStageFlags(VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, image_barrier);
cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_COMPUTE, vk_pipeline);
});
for (const VideoCommon::SwizzleParameters& swizzle : swizzles) {
@@ -648,7 +648,7 @@ void ASTCDecoderPass::Assemble(Image& image, const StagingBufferRef& map,
},
};
cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, 0, image_barrier);
vk::PIPELINE_STAGE_GRAPHICS_COMPUTE, 0, image_barrier);
});
scheduler.Finish();
}

Some files were not shown because too many files have changed in this diff Show More