Compare commits

...
Sign in to create a new pull request.

17 commits

Author SHA1 Message Date
896bfcdaaa
[vk] revert pApplicationName (#144)
Reverts Vulkan pApplicationName to fix rdna3 lines appearing (tested on totk gloom)

Co-authored-by: Maufeat <sahyno1996@gmail.com>
Reviewed-on: eden-emu/eden#144
Co-authored-by: Maufeat <maufeat@eden-emu.dev>
Co-committed-by: Maufeat <maufeat@eden-emu.dev>
2025-07-28 01:10:16 +02:00
9ccb792d29
[externals] fix cpp-httplib on Gentoo
Signed-off-by: crueter <crueter@eden-emu.dev>
2025-07-27 18:31:58 -04:00
bbeb7dd56b
[ssl] add and unstub alpn option + functions (#142)
Should fix Jackbox 7,8,9,10 unable to connect to server errors. (See discord issues)

Co-authored-by: Maufeat <sahyno1996@gmail.com>
Reviewed-on: eden-emu/eden#142
Co-authored-by: Maufeat <maufeat@eden-emu.dev>
Co-committed-by: Maufeat <maufeat@eden-emu.dev>
2025-07-27 22:06:22 +02:00
eeb68768d6
[vk] Exclude size equal alpha different copies from incompatible copy (#138)
Should fix bugs in Splatoon 2 and TotK

Co-authored-by: Maufeat <sahyno1996@gmail.com>
Reviewed-on: eden-emu/eden#138
Co-authored-by: JPikachu <jpikachu@eden-emu.dev>
Co-committed-by: JPikachu <jpikachu@eden-emu.dev>
2025-07-27 19:56:22 +02:00
0b29fb7c8a
[audio_core] Revert EA3835 audio sink changes (#136)
Fixes diablo/totk audio stutters

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

Reviewed-on: eden-emu/eden#136
2025-07-27 19:46:54 +02:00
b2914247c3
[cmake] Build presets and System profiles (#135)
- Build Preset (Linux only): enables arch optimizations, e.g. generic,
  v3, zen2/4, armv8, armv9
- System Profiles: currently only steamdeck, uses an older sdl commit to
  fix virtual gamepad bug

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

Reviewed-on: eden-emu/eden#135
2025-07-27 06:36:33 +02:00
b5bbe6d865
[externals] Update some submodules (#119)
This updates some submodules to keep the project in sync with the latest, stable fixes.

Reviewed-on: eden-emu/eden#119
Co-authored-by: MaranBr <maranbr@outlook.com>
Co-committed-by: MaranBr <maranbr@outlook.com>
2025-07-27 02:41:08 +02:00
77a8f7b6a7
[vk, hle] fix storage buffer cache, unstubbed TryPopFriendInvitation (#129)
This fixes Jamboree + unstubes friend invitation channel which spammed a lot while testing jamboree.

Culprit was: #2

Co-authored-by: Maufeat <sahyno1996@gmail.com>
Co-authored-by: crueter <crueter@eden-emu.dev>
Reviewed-on: eden-emu/eden#129
Co-authored-by: Maufeat <maufeat@eden-emu.dev>
Co-committed-by: Maufeat <maufeat@eden-emu.dev>
2025-07-27 02:37:29 +02:00
3bcd5f95fe
[git] fix dup xbyak (#140)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: eden-emu/eden#140
2025-07-27 02:36:18 +02:00
12d8cf79ea
Revert "[nvnflinger] unstub AdjustRefcount (#120)"
This reverts commit 410e782291.
2025-07-26 20:20:03 -04:00
fac153509a
[externals] Revert xbyak to v7.22 (#137)
Signed-off-by: crueter <crueter@eden-emu.dev>
Reviewed-on: eden-emu/eden#137
2025-07-26 23:06:14 +02:00
b1f3b568fb
[vk] Fix query cache leak on missed sync (#131)
Provided by community member, elementary-particle. Submitted as PR by MaranBR.

Fixed issues:

1. The queue cache forgot to put the host query into unregister queue if they weren't synced. This will block all the banks from freeing causing a major leak.

2. SamplesQueryCounter is not aligned with renderpass begin/end. This creates invalid queries.

3. Conditional rendering is not turned on/off at the correct location making them invalid.

Co-authored-by: Maufeat <sahyno1996@gmail.com>
Reviewed-on: eden-emu/eden#131
Co-authored-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-committed-by: Shinmegumi <shinmegumi@eden-emu.dev>
2025-07-26 18:12:54 +02:00
c7c2ed7b46
[vk] copy incompatible alpha patch 1.5(2) (#123)
Avoid copy size incompatible textures and reinterpret it instead. Uses existing logic to properly re-interpret to a compatible texture.

Reviewed-on: eden-emu/eden#123
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-07-26 05:58:04 +02:00
ac675c5296
[core]: Custom CPU Ticks rewrite (#118)
For now this is for testing purposes

Co-authored-by: Gamer64 <76565986+Gamer64ytb@users.noreply.github.com>
Reviewed-on: eden-emu/eden#118
Co-authored-by: Gamer64 <gamer64@eden-emu.dev>
Co-committed-by: Gamer64 <gamer64@eden-emu.dev>
2025-07-26 04:11:40 +02:00
8dd0e84343
[android, ci] disable workflows, update ERF desc, default flush_lines to on (#132)
title says it all

Reviewed-on: eden-emu/eden#132
2025-07-26 03:59:33 +02:00
410e782291
[nvnflinger] unstub AdjustRefcount (#120)
Co-authored-by: Maufeat <sahyno1996@gmail.com>
Reviewed-on: eden-emu/eden#120
Co-authored-by: Maufeat <maufeat@eden-emu.dev>
Co-committed-by: Maufeat <maufeat@eden-emu.dev>
2025-07-25 19:58:35 +02:00
5de03f47df
[renderdoc] update (#100)
Reviewed-on: eden-emu/eden#100
Co-authored-by: lizzie <lizzie@eden-emu.dev>
Co-committed-by: lizzie <lizzie@eden-emu.dev>
2025-07-25 09:52:12 +02:00
40 changed files with 526 additions and 216 deletions

View file

@ -3,47 +3,53 @@
# SPDX-FileCopyrightText: 2025 eden Emulator Project
# SPDX-License-Identifier: GPL-3.0-or-later
case "$1" in
amd64|"")
echo "Making amd64-v3 optimized build of Eden"
ARCH="amd64_v3"
ARCH_FLAGS="-march=x86-64-v3"
;;
steamdeck|zen2)
echo "Making Steam Deck (Zen 2) optimized build of Eden"
ARCH="steamdeck"
ARCH_FLAGS="-march=znver2 -mtune=znver2"
;;
rog-ally|allyx|zen4)
echo "Making ROG Ally X (Zen 4) optimized build of Eden"
ARCH="rog-ally-x"
ARCH_FLAGS="-march=znver4 -mtune=znver4"
;;
legacy)
echo "Making amd64 generic build of Eden"
ARCH=amd64
ARCH_FLAGS="-march=x86-64 -mtune=generic"
;;
aarch64)
echo "Making armv8-a build of Eden"
ARCH=aarch64
ARCH_FLAGS="-march=armv8-a -mtune=generic -w"
;;
armv9)
echo "Making armv9-a build of Eden"
ARCH=armv9
ARCH_FLAGS="-march=armv9-a -mtune=generic -w"
;;
native)
echo "Making native build of Eden"
ARCH="$(uname -m)"
ARCH_FLAGS="-march=native -mtune=native"
;;
*)
echo "Invalid target $1 specified, must be one of native, amd64, steamdeck, zen2, allyx, rog-ally, zen4, legacy, aarch64, armv9"
exit 1
;;
amd64 | "")
echo "Making amd64-v3 optimized build of Eden"
ARCH="amd64_v3"
ARCH_FLAGS="-march=x86-64-v3"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=v3)
;;
steamdeck | zen2)
echo "Making Steam Deck (Zen 2) optimized build of Eden"
ARCH="steamdeck"
ARCH_FLAGS="-march=znver2 -mtune=znver2"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=zen2 -DYUZU_SYSTEM_PROFILE=steamdeck)
;;
rog-ally | allyx | zen4)
echo "Making ROG Ally X (Zen 4) optimized build of Eden"
ARCH="rog-ally-x"
ARCH_FLAGS="-march=znver4 -mtune=znver4"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=zen2 -DYUZU_SYSTEM_PROFILE=steamdeck)
;;
legacy)
echo "Making amd64 generic build of Eden"
ARCH=amd64
ARCH_FLAGS="-march=x86-64 -mtune=generic"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=generic)
;;
aarch64)
echo "Making armv8-a build of Eden"
ARCH=aarch64
ARCH_FLAGS="-march=armv8-a -mtune=generic -w"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=generic)
;;
armv9)
echo "Making armv9-a build of Eden"
ARCH=armv9
ARCH_FLAGS="-march=armv9-a -mtune=generic -w"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=armv9)
;;
native)
echo "Making native build of Eden"
ARCH="$(uname -m)"
ARCH_FLAGS="-march=native -mtune=native"
export EXTRA_CMAKE_FLAGS=(-DYUZU_BUILD_PRESET=native)
;;
*)
echo "Invalid target $1 specified, must be one of native, amd64, steamdeck, zen2, allyx, rog-ally, zen4, legacy, aarch64, armv9"
exit 1
;;
esac
export ARCH_FLAGS="$ARCH_FLAGS -O3"
@ -55,10 +61,10 @@ fi
if [ "$1" != "" ]; then shift; fi
if [ "$TARGET" = "appimage" ]; then
export EXTRA_CMAKE_FLAGS=(-DCMAKE_INSTALL_PREFIX=/usr -DYUZU_ROOM=ON -DYUZU_ROOM_STANDALONE=OFF -DYUZU_CMD=OFF)
export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DCMAKE_INSTALL_PREFIX=/usr -DYUZU_ROOM=ON -DYUZU_ROOM_STANDALONE=OFF -DYUZU_CMD=OFF)
else
# For the linux-fresh verification target, verify compilation without PCH as well.
export EXTRA_CMAKE_FLAGS=(-DYUZU_USE_PRECOMPILED_HEADERS=OFF)
export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" -DYUZU_USE_PRECOMPILED_HEADERS=OFF)
fi
if [ "$DEVEL" != "true" ]; then
@ -86,7 +92,7 @@ export EXTRA_CMAKE_FLAGS=("${EXTRA_CMAKE_FLAGS[@]}" $@)
mkdir -p build && cd build
cmake .. -G Ninja \
-DCMAKE_BUILD_TYPE="$BUILD_TYPE" \
-DENABLE_QT_TRANSLATION=ON \
-DENABLE_QT_TRANSLATION=ON \
-DUSE_DISCORD_PRESENCE=ON \
-DCMAKE_CXX_FLAGS="$ARCH_FLAGS" \
-DCMAKE_C_FLAGS="$ARCH_FLAGS" \
@ -99,12 +105,12 @@ cmake .. -G Ninja \
-DYUZU_USE_QT_WEB_ENGINE=$WEBENGINE \
-DYUZU_USE_FASTER_LD=ON \
-DYUZU_ENABLE_LTO=ON \
"${EXTRA_CMAKE_FLAGS[@]}"
"${EXTRA_CMAKE_FLAGS[@]}"
ninja -j${NPROC}
if [ -d "bin/Release" ]; then
strip -s bin/Release/*
strip -s bin/Release/*
else
strip -s bin/*
strip -s bin/*
fi

View file

@ -92,7 +92,6 @@ chmod +x ./sharun-aio
xvfb-run -a ./sharun-aio l -p -v -e -s -k \
../$BUILDDIR/bin/eden* \
$LIBDIR/lib*GL*.so* \
$LIBDIR/libSDL2*.so* \
$LIBDIR/dri/* \
$LIBDIR/vdpau/* \
$LIBDIR/libvulkan* \

View file

@ -2,9 +2,9 @@
# some stuff needs cleaned up etc
name: eden-build
on:
push:
branches: [ "master" ]
#on:
# push:
# branches: [ "master" ]
# TODO: combine build.yml into trigger_release.yml
jobs:

View file

@ -1,8 +1,8 @@
name: Build Application and Make Release
on:
push:
tags: [ "*" ]
#on:
# push:
# tags: [ "*" ]
permissions:
contents: write

6
.gitmodules vendored
View file

@ -16,9 +16,6 @@
[submodule "opus"]
path = externals/opus
url = https://github.com/xiph/opus.git
[submodule "SDL"]
path = externals/SDL
url = https://github.com/libsdl-org/SDL.git
[submodule "cpp-httplib"]
path = externals/cpp-httplib
url = https://github.com/yhirose/cpp-httplib.git
@ -49,9 +46,6 @@
[submodule "externals/dynarmic/externals/unordered_dense"]
path = externals/dynarmic/externals/unordered_dense
url = https://github.com/Lizzie841/unordered_dense.git
[submodule "externals/dynarmic/externals/xbyak"]
path = externals/dynarmic/externals/xbyak
url = https://github.com/Lizzie841/xbyak.git
[submodule "externals/dynarmic/externals/zycore-c"]
path = externals/dynarmic/externals/zycore-c
url = https://github.com/zyantific/zycore-c.git

View file

@ -33,9 +33,9 @@ endif()
option(ENABLE_SDL2 "Enable the SDL2 frontend" ON)
CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 binaries" ON "ENABLE_SDL2;MSVC" OFF)
if (${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "ENABLE_SDL2;NOT MSVC" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "ENABLE_SDL2;NOT MSVC" OFF)
else()
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ON "ENABLE_SDL2;NOT MSVC" OFF)
endif()
cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF)
@ -332,6 +332,41 @@ if (YUZU_ROOM)
add_definitions(-DYUZU_ROOM)
endif()
# Build/optimization presets
if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux")
if (ARCHITECTURE_x86_64)
set(YUZU_BUILD_PRESET "generic" CACHE STRING "Build preset to use. One of: generic, v3, zen2, zen4, native")
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64 -mtune=generic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64 -mtune=generic")
elseif (${YUZU_BUILD_PRESET} STREQUAL "v3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=x86-64-v3 -mtune=generic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=x86-64-v3 -mtune=generic")
elseif (${YUZU_BUILD_PRESET} STREQUAL "zen2")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=znver2 -mtune=znver2")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=znver2 -mtune=znver2")
elseif (${YUZU_BUILD_PRESET} STREQUAL "zen4")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=znver4 -mtune=znver4")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=znver4 -mtune=znver4")
elseif (${YUZU_BUILD_PRESET} STREQUAL "native")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=native -mtune=native")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=native -mtune=native")
endif()
elseif(ARCHITECTURE_arm64)
set(YUZU_BUILD_PRESET "generic" CACHE STRING "Build preset to use. One of: generic, armv9")
if (${YUZU_BUILD_PRESET} STREQUAL "generic")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv8-a -mtune=generic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv8-a -mtune=generic")
elseif (${YUZU_BUILD_PRESET} STREQUAL "armv9")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv9-a -mtune=generic")
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -march=armv9-a -mtune=generic")
endif()
endif()
endif()
# Other presets, e.g. steamdeck
set(YUZU_SYSTEM_PROFILE "generic" CACHE STRING "CMake and Externals profile to use. One of: generic, steamdeck")
# Configure C++ standard
# ===========================
@ -420,6 +455,7 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Linux" OR ANDROID)
endif()
# find SDL2 exports a bunch of variables that are needed, so its easier to do this outside of the YUZU_find_package
# TODO(crueter): combine this all with CPM.
if (ENABLE_SDL2)
if (YUZU_USE_BUNDLED_SDL2)
# Detect toolchain and platform

View file

@ -15,8 +15,7 @@
<br>
</h1>
<h4 align="center"><b>Eden</b> is a open-source Nintendo Switch emulator, forked from the Yuzu emulator — started by former Citron developer Camille LaVey and the Eden team.
<br>
<h4 align="center"><b>Eden</b> is an open-source Nintendo Switch emulator, forked from the Yuzu emulator — started by former Citron developer Camille LaVey and the Eden team.
It is written in C++ with portability in mind, and we actively maintain builds for Windows, Linux and Android.
</h4>
@ -76,7 +75,7 @@ Any donations received will go towards things such as:
* Additional hardware (e.g. GPUs as needed to improve rendering support, other peripherals to add support for, etc.)
* CI Infrastructure
If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/edenemu), once public, and talk to Camille or any of our other developers.
If you would prefer to support us in a different way, please join our [Discord](https://discord.gg/edenemu) and talk to Camille or any of our other developers.
## License

View file

@ -83,7 +83,18 @@ if (YUZU_USE_EXTERNAL_SDL2)
set(SDL_FILE ON)
endif()
add_subdirectory(SDL)
include(CPM)
set(CPM_SOURCE_CACHE ${CMAKE_SOURCE_DIR}/.cache/cpm)
set(CPM_USE_LOCAL_PACKAGES OFF)
if ("${YUZU_SYSTEM_PROFILE}" STREQUAL "steamdeck")
set(SDL_HASH cc016b0046)
set(SDL_PIPEWIRE OFF) # build errors out with this on
else()
set(SDL_HASH 2e4c12cd2c)
endif()
CPMAddPackage("gh:libsdl-org/SDL#${SDL_HASH}")
endif()
# ENet

1
externals/SDL vendored

@ -1 +0,0 @@
Subproject commit 2e4c12cd2cb2c5d0b60ef2196b400339591e733c

@ -1 +1 @@
Subproject commit 16cedde3564629c43808401ad1eb3ca6ef24709a
Subproject commit 89268a6d17fc87003b209a1422c17ab288be99a0

@ -1 +1 @@
Subproject commit f216bb107bfc6d99a9605572963613e828b10880
Subproject commit df2e3581520f36776cd42b9fec3ec4a51ab878ef

@ -1 +1 @@
Subproject commit 6ec8481c8a13db586d7b3ba58f4eb9bbf017edf0
Subproject commit 1076b348abd17859a116f4b111c43d58a588a086

2
externals/cubeb vendored

@ -1 +1 @@
Subproject commit 832fcf38e600bf80b4b728a3e0227403088d992c
Subproject commit fa021607121360af7c171d881dc5bc8af7bb56eb

View file

@ -64,12 +64,13 @@ if (NOT TARGET ankerl::unordered_dense)
endif()
# xbyak
# uncomment if in an independent repo.
if (NOT TARGET xbyak::xbyak)
if ("x86_64" IN_LIST ARCHITECTURE)
add_subdirectory(xbyak)
endif()
endif()
# if (NOT TARGET xbyak::xbyak)
# if ("x86_64" IN_LIST ARCHITECTURE)
# add_subdirectory(xbyak)
# endif()
# endif()
# zydis

@ -1 +0,0 @@
Subproject commit 12557954c68a780563f9ab9fc24a3a156c96cba1

@ -1 +1 @@
Subproject commit c060e9ce30ac2e3ffb49d94209c4dae77b6642f7
Subproject commit 3dbfa16f0cd9e8ed4fec916c6c00f41c738cb8f4

2
externals/opus vendored

@ -1 +1 @@
Subproject commit df02d25f0c6334a60f8c01c5ecf63081845d6c9d
Subproject commit 5ded705cf4ffa13702c78eebecea0fdb2f4ef0de

View file

@ -7,7 +7,7 @@
/******************************************************************************
* The MIT License (MIT)
*
* Copyright (c) 2019-2023 Baldur Karlsson
* Copyright (c) 2019-2025 Baldur Karlsson
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
@ -41,8 +41,12 @@
#if defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER)
#define RENDERDOC_CC __cdecl
#else
#elif defined(__linux__) || defined(__FreeBSD__) || defined(__sun__)
#define RENDERDOC_CC
#elif defined(__APPLE__)
#define RENDERDOC_CC
#else
#error "Unknown platform"
#endif
#ifdef __cplusplus
@ -357,14 +361,14 @@ typedef enum RENDERDOC_OverlayBits
eRENDERDOC_Overlay_FrameNumber | eRENDERDOC_Overlay_CaptureList),
// Enable all bits
eRENDERDOC_Overlay_All = ~0U,
eRENDERDOC_Overlay_All = 0x7ffffff,
// Disable all bits
eRENDERDOC_Overlay_None = 0,
} RENDERDOC_OverlayBits;
// returns the overlay bits that have been set
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetOverlayBits)(void);
// sets the overlay bits with an and & or mask
typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or);
@ -375,7 +379,7 @@ typedef void(RENDERDOC_CC *pRENDERDOC_MaskOverlayBits)(uint32_t And, uint32_t Or
// injected hooks and shut down. Behaviour is undefined if this is called
// after any API functions have been called, and there is still no guarantee of
// success.
typedef void(RENDERDOC_CC *pRENDERDOC_RemoveHooks)();
typedef void(RENDERDOC_CC *pRENDERDOC_RemoveHooks)(void);
// DEPRECATED: compatibility for code compiled against pre-1.4.1 headers.
typedef pRENDERDOC_RemoveHooks pRENDERDOC_Shutdown;
@ -385,7 +389,7 @@ typedef pRENDERDOC_RemoveHooks pRENDERDOC_Shutdown;
// If you use your own crash handler and don't want RenderDoc's handler to
// intercede, you can call this function to unload it and any unhandled
// exceptions will pass to the next handler.
typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)(void);
// Sets the capture file path template
//
@ -407,14 +411,14 @@ typedef void(RENDERDOC_CC *pRENDERDOC_UnloadCrashHandler)();
typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureFilePathTemplate)(const char *pathtemplate);
// returns the current capture path template, see SetCaptureFileTemplate above, as a UTF-8 string
typedef const char *(RENDERDOC_CC *pRENDERDOC_GetCaptureFilePathTemplate)();
typedef const char *(RENDERDOC_CC *pRENDERDOC_GetCaptureFilePathTemplate)(void);
// DEPRECATED: compatibility for code compiled against pre-1.1.2 headers.
typedef pRENDERDOC_SetCaptureFilePathTemplate pRENDERDOC_SetLogFilePathTemplate;
typedef pRENDERDOC_GetCaptureFilePathTemplate pRENDERDOC_GetLogFilePathTemplate;
// returns the number of captures that have been made
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_GetNumCaptures)(void);
// This function returns the details of a capture, by index. New captures are added
// to the end of the list.
@ -445,7 +449,7 @@ typedef void(RENDERDOC_CC *pRENDERDOC_SetCaptureFileComments)(const char *filePa
const char *comments);
// returns 1 if the RenderDoc UI is connected to this application, 0 otherwise
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsTargetControlConnected)(void);
// DEPRECATED: compatibility for code compiled against pre-1.1.1 headers.
// This was renamed to IsTargetControlConnected in API 1.1.1, the old typedef is kept here for
@ -477,7 +481,7 @@ typedef void(RENDERDOC_CC *pRENDERDOC_GetAPIVersion)(int *major, int *minor, int
// This will return 1 if the request was successfully passed on, though it's not guaranteed that
// the UI will be on top in all cases depending on OS rules. It will return 0 if there is no current
// target control connection to make such a request, or if there was another error
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_ShowReplayUI)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_ShowReplayUI)(void);
//////////////////////////////////////////////////////////////////////////
// Capturing functions
@ -508,7 +512,7 @@ typedef void(RENDERDOC_CC *pRENDERDOC_SetActiveWindow)(RENDERDOC_DevicePointer d
RENDERDOC_WindowHandle wndHandle);
// capture the next frame on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)();
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerCapture)(void);
// capture the next N frames on whichever window and API is currently considered active
typedef void(RENDERDOC_CC *pRENDERDOC_TriggerMultiFrameCapture)(uint32_t numFrames);
@ -537,7 +541,7 @@ typedef void(RENDERDOC_CC *pRENDERDOC_StartFrameCapture)(RENDERDOC_DevicePointer
// Returns whether or not a frame capture is currently ongoing anywhere.
//
// This will return 1 if a capture is ongoing, and 0 if there is no capture running
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)();
typedef uint32_t(RENDERDOC_CC *pRENDERDOC_IsFrameCapturing)(void);
// Ends capturing immediately.
//

2
externals/xbyak vendored

@ -1 +1 @@
Subproject commit 12557954c68a780563f9ab9fc24a3a156c96cba1
Subproject commit 4e44f4614ddbf038f2a6296f5b906d5c72691e0f

View file

@ -89,7 +89,7 @@
<string name="frame_interpolation">Enhanced Frame Pacing</string>
<string name="frame_interpolation_description">Ensures smooth and consistent frame delivery by synchronizing the timing between frames, reducing stuttering and uneven animation. Ideal for games that experience frame timing instability or micro-stutters during gameplay.</string>
<string name="renderer_early_release_fences">Release fences early</string>
<string name="renderer_early_release_fences_description">Some games may require this to get past 0FPS errors, such as DKCR:HD, Subnautica, and Ori 2.</string>
<string name="renderer_early_release_fences_description">Some games may require this to get past 0FPS errors, such as DKCR:HD, Subnautica, and Ori 2. Other games, notably Unreal Engine games, may work improperly or not boot with this enabled.</string>
<string name="veil_misc">CPU and Memory</string>
<string name="use_sync_core">Synchronize Core Speed</string>

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -334,6 +337,48 @@ std::vector<std::string> ListCubebSinkDevices(bool capture) {
return device_list;
}
/* REVERSION TO 3833 - function GetCubebLatency REINTRODUCED FROM 3833 - DIABLO 3 FIX */
u32 GetCubebLatency() {
cubeb* ctx;
#ifdef _WIN32
auto com_init_result = CoInitializeEx(nullptr, COINIT_MULTITHREADED);
#endif
// Init cubeb
if (cubeb_init(&ctx, "yuzu Latency Getter", nullptr) != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "cubeb_init failed");
// Return a large latency so we choose SDL instead.
return 10000u;
}
#ifdef _WIN32
if (SUCCEEDED(com_init_result)) {
CoUninitialize();
}
#endif
// Get min latency
cubeb_stream_params params{};
params.rate = TargetSampleRate;
params.channels = 2;
params.format = CUBEB_SAMPLE_S16LE;
params.prefs = CUBEB_STREAM_PREF_NONE;
params.layout = CUBEB_LAYOUT_STEREO;
u32 latency{0};
const auto latency_error = cubeb_get_min_latency(ctx, &params, &latency);
if (latency_error != CUBEB_OK) {
LOG_CRITICAL(Audio_Sink, "Error getting minimum latency, error: {}", latency_error);
latency = TargetSampleCount * 2;
}
latency = std::max(latency, TargetSampleCount * 2);
cubeb_destroy(ctx);
return latency;
}
// REVERTED back to 3833 - Below namespace section and function IsCubebSuitable() removed, reverting to GetCubebLatency() above. - DIABLO 3 FIX
/*
namespace {
static long TmpDataCallback(cubeb_stream*, void*, const void*, void*, long) {
return TargetSampleCount;
@ -400,5 +445,6 @@ bool IsCubebSuitable() {
return true;
#endif
}
*/
} // namespace AudioCore::Sink

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -96,12 +99,20 @@ private:
*/
std::vector<std::string> ListCubebSinkDevices(bool capture);
// REVERSION - function GetCubebLatency() reintroduced from EA-3833 - DIABLO 3 FIX
/**
* Get the reported latency for this sink.
*
* @return Minimum latency for this sink.
*/
u32 GetCubebLatency();
/**
* Check if this backend is suitable for use.
* Checks if enabled, its latency, whether it opens successfully, etc.
*
* @return True is this backend is suitable, false otherwise.
*/
bool IsCubebSuitable();
// bool IsCubebSuitable(); // REVERTED BACK TO GetCubebLatency() FROM 3833
} // namespace AudioCore::Sink

View file

@ -234,6 +234,13 @@ std::vector<std::string> ListSDLSinkDevices(bool capture) {
return device_list;
}
/* REVERSION to 3833 - function GetSDLLatency() REINTRODUCED FROM 3833 - DIABLO 3 FIX */
u32 GetSDLLatency() {
return TargetSampleCount * 2;
}
// REVERTED back to 3833 - Below function IsSDLSuitable() removed, reverting to GetSDLLatency() above. - DIABLO 3 FIX
/*
bool IsSDLSuitable() {
#if !defined(HAVE_SDL2)
return false;
@ -271,5 +278,6 @@ bool IsSDLSuitable() {
return true;
#endif
}
*/
} // namespace AudioCore::Sink

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -87,12 +90,20 @@ private:
*/
std::vector<std::string> ListSDLSinkDevices(bool capture);
// REVERSION - function GetSDLLatency() reintroduced from EA-3833 - DIABLO 3 FIX
/**
* Get the reported latency for this sink.
*
* @return Minimum latency for this sink.
*/
u32 GetSDLLatency();
/** REVERTED back to 3833 - Below function IsSDLSuitable() removed, reverting to GetSDLLatency() above. - DIABLO 3 FIX
* Check if this backend is suitable for use.
* Checks if enabled, its latency, whether it opens successfully, etc.
*
* @return True is this backend is suitable, false otherwise.
*/
bool IsSDLSuitable();
//bool IsSDLSuitable(); // REVERTED for GetSDLLatency() from EA-3833
} // namespace AudioCore::Sink

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -25,7 +28,8 @@ namespace {
struct SinkDetails {
using FactoryFn = std::unique_ptr<Sink> (*)(std::string_view);
using ListDevicesFn = std::vector<std::string> (*)(bool);
using SuitableFn = bool (*)();
using LatencyFn = u32 (*)(); // REINTRODUCED FROM 3833 - DIABLO 3 FIX
// using SuitableFn = bool (*)(); // REVERTED FOR ABOVE - DIABLO 3 FIX
/// Name for this sink.
Settings::AudioEngine id;
@ -33,10 +37,18 @@ struct SinkDetails {
FactoryFn factory;
/// A method to call to list available devices.
ListDevicesFn list_devices;
/// Method to get the latency of this backend - REINTRODUCED FROM 3833 - DIABLO 3 FIX
LatencyFn latency;
/// Check whether this backend is suitable to be used.
SuitableFn is_suitable;
/// SuitableFn is_suitable; // REVERTED FOR LatencyFn latency ABOVE - DIABLO 3 FIX
};
// NOTE TO PROBABLY FIX LATER FOR ANDROID - the return value "0u" for the first HAVE_OBOE
// section below was just copied from the null section so there's a somewhat valid value
// being returned, since the previous "true" value probably isn't compatible with the
// previous EA-3833 code. (HAVE_OBOE was introduced in a later release.) Eventually need
// to change "0u" for something else directly from the oboe_sink.cpp functions.
// sink_details is ordered in terms of desirability, with the best choice at the top.
constexpr SinkDetails sink_details[] = {
#ifdef HAVE_OBOE
@ -46,7 +58,7 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<OboeSink>();
},
[](bool capture) { return std::vector<std::string>{"Default"}; },
[]() { return true; },
[]() { return 0u; },
},
#endif
#ifdef HAVE_CUBEB
@ -56,7 +68,7 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<CubebSink>(device_id);
},
&ListCubebSinkDevices,
&IsCubebSuitable,
&GetCubebLatency,
},
#endif
#ifdef HAVE_SDL2
@ -66,7 +78,7 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<SDLSink>(device_id);
},
&ListSDLSinkDevices,
&IsSDLSuitable,
&GetSDLLatency,
},
#endif
SinkDetails{
@ -75,7 +87,7 @@ constexpr SinkDetails sink_details[] = {
return std::make_unique<NullSink>(device_id);
},
[](bool capture) { return std::vector<std::string>{"null"}; },
[]() { return true; },
[]() { return 0u; },
},
};
@ -88,6 +100,8 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
auto iter = find_backend(sink_id);
if (sink_id == Settings::AudioEngine::Auto) {
// REVERTED TO 3833 BELOW - DIABLO 3 FIX
/*
// Auto-select a backend. Use the sink details ordering, preferring cubeb first, checking
// that the backend is available and suitable to use.
for (auto& details : sink_details) {
@ -96,14 +110,29 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
break;
}
}
*/ // END REVERTED CODE - DIABLO 3 FIX
// BEGIN REINTRODUCED FROM 3833 - REPLACED CODE BLOCK ABOVE - DIABLO 3 FIX
// Auto-select a backend. Prefer CubeB, but it may report a large minimum latency which
// causes audio issues, in that case go with SDL.
#if defined(HAVE_CUBEB) && defined(HAVE_SDL2)
iter = find_backend(Settings::AudioEngine::Cubeb);
if (iter->latency() > TargetSampleCount * 3) {
iter = find_backend(Settings::AudioEngine::Sdl2);
}
#else
iter = std::begin(sink_details);
#endif
// END REINTRODUCED SECTION FROM 3833 - DIABLO 3 FIX
LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
Settings::CanonicalizeEnum(iter->id));
/* BEGIN REMOVED - REVERTING BACK TO 3833, this didn't exist at all. - DIABLO 3 FIX
} else {
if (iter != std::end(sink_details) && !iter->is_suitable()) {
LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null",
Settings::CanonicalizeEnum(iter->id));
iter = find_backend(Settings::AudioEngine::Null);
}
} */ // END REMOVED REVERT - DIABLO 3 FIX
}
if (iter == std::end(sink_details)) {

View file

@ -705,7 +705,7 @@ struct Values {
// Miscellaneous
Setting<std::string> log_filter{linkage, "*:Info", "log_filter", Category::Miscellaneous};
Setting<bool> log_flush_lines{linkage, false, "flush_lines", Category::Miscellaneous};
Setting<bool> log_flush_lines{linkage, true, "flush_lines", Category::Miscellaneous, Specialization::Default, true, true};
Setting<bool> censor_username{linkage, true, "censor_username", Category::Miscellaneous};
Setting<bool> use_dev_keys{linkage, false, "use_dev_keys", Category::Miscellaneous};
Setting<bool> first_launch{linkage, true, "first_launch", Category::Miscellaneous};

View file

@ -174,15 +174,21 @@ void CoreTiming::UnscheduleEvent(const std::shared_ptr<EventType>& event_type,
}
}
static u64 GetNextTickCount(u64 next_ticks) {
if (Settings::values.use_custom_cpu_ticks.GetValue()) {
return Settings::values.cpu_ticks.GetValue();
}
return next_ticks;
}
void CoreTiming::AddTicks(u64 ticks_to_add) {
cpu_ticks = Settings::values.use_custom_cpu_ticks.GetValue()
? Settings::values.cpu_ticks.GetValue()
: cpu_ticks + ticks_to_add;
downcount -= static_cast<s64>(cpu_ticks);
const u64 ticks = GetNextTickCount(ticks_to_add);
cpu_ticks += ticks;
downcount -= static_cast<s64>(ticks);
}
void CoreTiming::Idle() {
cpu_ticks += 1000U;
AddTicks(1000U);
}
void CoreTiming::ResetTicks() {

View file

@ -92,6 +92,7 @@ struct Applet {
// Channels
std::deque<std::vector<u8>> user_channel_launch_parameter{};
std::deque<std::vector<u8>> preselected_user_launch_parameter{};
std::deque<std::vector<u8>> friend_invitation_storage_channel{};
// Caller applet
std::weak_ptr<Applet> caller_applet{};

View file

@ -456,8 +456,21 @@ Result IApplicationFunctions::GetFriendInvitationStorageChannelEvent(
Result IApplicationFunctions::TryPopFromFriendInvitationStorageChannel(
Out<SharedPointer<IStorage>> out_storage) {
LOG_INFO(Service_AM, "(STUBBED) called");
R_THROW(AM::ResultNoDataInChannel);
LOG_DEBUG(Service_AM, "called");
std::scoped_lock lk{m_applet->lock};
auto& channel = m_applet->friend_invitation_storage_channel;
if (channel.empty()) {
return AM::ResultNoDataInChannel;
}
auto data = channel.back();
channel.pop_back();
*out_storage = std::make_shared<IStorage>(system, std::move(data));
R_SUCCEED();
}
Result IApplicationFunctions::GetNotificationStorageChannelEvent(

View file

@ -41,6 +41,8 @@ enum class IoMode : u32 {
enum class OptionType : u32 {
DoNotCloseSocket = 0,
GetServerCertChain = 1,
SkipDefaultVerify = 2,
EnableAlpn = 3,
};
// This is nn::ssl::sf::SslVersion
@ -93,11 +95,11 @@ public:
{20, nullptr, "SetRenegotiationMode"},
{21, nullptr, "GetRenegotiationMode"},
{22, &ISslConnection::SetOption, "SetOption"},
{23, nullptr, "GetOption"},
{23, &ISslConnection::GetOption, "GetOption"},
{24, nullptr, "GetVerifyCertErrors"},
{25, nullptr, "GetCipherInfo"},
{26, nullptr, "SetNextAlpnProto"},
{27, nullptr, "GetNextAlpnProto"},
{26, &ISslConnection::SetNextAlpnProto, "SetNextAlpnProto"},
{27, &ISslConnection::GetNextAlpnProto, "GetNextAlpnProto"},
{28, nullptr, "SetDtlsSocketDescriptor"},
{29, nullptr, "GetDtlsHandshakeTimeout"},
{30, nullptr, "SetPrivateOption"},
@ -140,7 +142,10 @@ private:
std::optional<int> fd_to_close;
bool do_not_close_socket = false;
bool get_server_cert_chain = false;
bool skip_default_verify = false;
bool enable_alpn = false;
std::shared_ptr<Network::SocketBase> socket;
std::vector<u8> next_alpn_proto;
bool did_handshake = false;
Result SetSocketDescriptorImpl(s32* out_fd, s32 fd) {
@ -381,6 +386,12 @@ private:
case OptionType::GetServerCertChain:
get_server_cert_chain = static_cast<bool>(parameters.value);
break;
case OptionType::SkipDefaultVerify:
skip_default_verify = static_cast<bool>(parameters.value);
break;
case OptionType::EnableAlpn:
enable_alpn = static_cast<bool>(parameters.value);
break;
default:
LOG_WARNING(Service_SSL, "Unknown option={}, value={}", parameters.option,
parameters.value);
@ -389,6 +400,63 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetOption(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto option = rp.PopRaw<OptionType>();
u8 value = 0;
switch (option) {
case OptionType::DoNotCloseSocket:
value = static_cast<u8>(do_not_close_socket);
break;
case OptionType::GetServerCertChain:
value = static_cast<u8>(get_server_cert_chain);
break;
case OptionType::SkipDefaultVerify:
value = static_cast<u8>(skip_default_verify);
break;
case OptionType::EnableAlpn:
value = static_cast<u8>(enable_alpn);
break;
default:
LOG_WARNING(Service_SSL, "Unknown option={}", option);
value = 0;
break;
}
LOG_DEBUG(Service_SSL, "GetOption called, option={}, ret value={}", option, value);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u8>(value);
}
void SetNextAlpnProto(HLERequestContext& ctx) {
const auto data = ctx.ReadBuffer(0);
next_alpn_proto.assign(data.begin(), data.end());
LOG_DEBUG(Service_SSL, "SetNextAlpnProto called, size={}", next_alpn_proto.size());
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetNextAlpnProto(HLERequestContext& ctx) {
const size_t writable = ctx.GetWriteBufferSize();
const size_t to_write = std::min(next_alpn_proto.size(), writable);
if (to_write != 0) {
ctx.WriteBuffer(std::span<const u8>(next_alpn_proto.data(), to_write));
}
LOG_DEBUG(Service_SSL, "GetNextAlpnProto called, size={}", to_write);
IPC::ResponseBuilder rb{ctx, 3};
rb.Push(ResultSuccess);
rb.Push<u32>(static_cast<u32>(to_write));
}
};
class ISslContext final : public ServiceFramework<ISslContext> {
@ -398,7 +466,7 @@ public:
shared_data{std::make_shared<SslContextSharedData>()} {
static const FunctionInfo functions[] = {
{0, &ISslContext::SetOption, "SetOption"},
{1, nullptr, "GetOption"},
{1, &ISslContext::GetOption, "GetOption"},
{2, &ISslContext::CreateConnection, "CreateConnection"},
{3, &ISslContext::GetConnectionCount, "GetConnectionCount"},
{4, &ISslContext::ImportServerPki, "ImportServerPki"},
@ -434,6 +502,17 @@ private:
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void GetOption(HLERequestContext& ctx) {
IPC::RequestParser rp{ctx};
const auto parameters = rp.PopRaw<OptionType>();
LOG_WARNING(Service_SSL, "(STUBBED) called. option={}", parameters);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
}
void CreateConnection(HLERequestContext& ctx) {

View file

@ -467,6 +467,10 @@ void BufferCache<P>::BindComputeStorageBuffer(size_t ssbo_index, u32 cbuf_index,
channel_state->written_compute_storage_buffers |= (is_written ? 1U : 0U) << ssbo_index;
const auto& launch_desc = kepler_compute->launch_description;
if (((launch_desc.const_buffer_enable_mask >> cbuf_index) & 1) == 0) {
LOG_WARNING(HW_GPU, "Skipped binding SSBO: cbuf index {} is not enabled", cbuf_index);
return;
}
ASSERT(((launch_desc.const_buffer_enable_mask >> cbuf_index) & 1) != 0);
const auto& cbufs = launch_desc.const_buffer_config;
@ -1701,6 +1705,11 @@ template <class P>
Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
bool is_written) const {
const GPUVAddr gpu_addr = gpu_memory->Read<u64>(ssbo_addr);
if (gpu_addr == 0) {
return NULL_BINDING;
}
const auto size = [&]() {
const bool is_nvn_cbuf = cbuf_index == 0;
// The NVN driver buffer (index 0) is known to pack the SSBO address followed by its size.
@ -1723,7 +1732,7 @@ Binding BufferCache<P>::StorageBufferBinding(GPUVAddr ssbo_addr, u32 cbuf_index,
const std::optional<DAddr> aligned_device_addr = gpu_memory->GpuToCpuAddress(aligned_gpu_addr);
if (!aligned_device_addr || size == 0) {
LOG_WARNING(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index);
LOG_DEBUG(HW_GPU, "Failed to find storage buffer for cbuf index {}", cbuf_index);
return NULL_BINDING;
}
const std::optional<DAddr> device_addr = gpu_memory->GpuToCpuAddress(gpu_addr);

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -115,8 +118,8 @@ struct QueryCacheBase<Traits>::QueryCacheBaseImpl {
QueryCacheBaseImpl(QueryCacheBase<Traits>* owner_, VideoCore::RasterizerInterface& rasterizer_,
Tegra::MaxwellDeviceMemoryManager& device_memory_, RuntimeType& runtime_,
Tegra::GPU& gpu_)
: owner{owner_}, rasterizer{rasterizer_},
device_memory{device_memory_}, runtime{runtime_}, gpu{gpu_} {
: owner{owner_}, rasterizer{rasterizer_}, device_memory{device_memory_}, runtime{runtime_},
gpu{gpu_} {
streamer_mask = 0;
for (size_t i = 0; i < static_cast<size_t>(QueryType::MaxQueryTypes); i++) {
streamers[i] = runtime.GetStreamerInterface(static_cast<QueryType>(i));
@ -267,7 +270,11 @@ void QueryCacheBase<Traits>::CounterReport(GPUVAddr addr, QueryType counter_type
return;
}
if (False(query_base->flags & QueryFlagBits::IsFinalValueSynced)) [[unlikely]] {
ASSERT(false);
LOG_ERROR(HW_GPU,
"Query report value not synchronized. Consider increasing GPU accuracy.");
if (!is_synced) [[likely]] {
impl->pending_unregister.push_back(query_location);
}
return;
}
query_base->value += streamer->GetAmendValue();
@ -370,8 +377,6 @@ void QueryCacheBase<Traits>::NotifySegment(bool resume) {
if (resume) {
impl->runtime.ResumeHostConditionalRendering();
} else {
CounterClose(VideoCommon::QueryType::ZPassPixelCount64);
CounterClose(VideoCommon::QueryType::StreamingByteCount);
impl->runtime.PauseHostConditionalRendering();
}
}

View file

@ -324,9 +324,8 @@ bool GraphicsPipeline::ConfigureImpl(bool is_indexed) {
size_t ssbo_index{};
for (const auto& desc : info.storage_buffers_descriptors) {
ASSERT(desc.count == 1);
if (!buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index,
desc.cbuf_offset, desc.is_written))
return false;
buffer_cache.BindGraphicsStorageBuffer(stage, ssbo_index, desc.cbuf_index,
desc.cbuf_offset, desc.is_written);
++ssbo_index;
}
}

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -1161,10 +1164,9 @@ struct QueryCacheRuntimeImpl {
StagingBufferPool& staging_pool_,
ComputePassDescriptorQueue& compute_pass_descriptor_queue,
DescriptorPool& descriptor_pool)
: rasterizer{rasterizer_}, device_memory{device_memory_},
buffer_cache{buffer_cache_}, device{device_},
memory_allocator{memory_allocator_}, scheduler{scheduler_}, staging_pool{staging_pool_},
guest_streamer(0, runtime),
: rasterizer{rasterizer_}, device_memory{device_memory_}, buffer_cache{buffer_cache_},
device{device_}, memory_allocator{memory_allocator_}, scheduler{scheduler_},
staging_pool{staging_pool_}, guest_streamer(0, runtime),
sample_streamer(static_cast<size_t>(QueryType::ZPassPixelCount64), runtime, rasterizer,
device, scheduler, memory_allocator, compute_pass_descriptor_queue,
descriptor_pool),
@ -1300,9 +1302,11 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
if (impl->hcr_is_set) {
if (impl->hcr_setup.buffer == impl->hcr_buffer &&
impl->hcr_setup.offset == impl->hcr_offset) {
ResumeHostConditionalRendering();
return;
}
}
bool was_running = impl->is_hcr_running;
if (was_running) {
PauseHostConditionalRendering();
}
impl->hcr_setup.buffer = impl->hcr_buffer;
@ -1310,7 +1314,9 @@ void QueryCacheRuntime::HostConditionalRenderingCompareValueImpl(VideoCommon::Lo
impl->hcr_setup.flags = is_equal ? VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT : 0;
impl->hcr_is_set = true;
impl->is_hcr_running = false;
ResumeHostConditionalRendering();
if (was_running) {
ResumeHostConditionalRendering();
}
}
void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, bool is_equal) {
@ -1325,7 +1331,8 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo
to_resolve = buffer->Handle();
to_resolve_offset = static_cast<u32>(offset);
}
if (impl->is_hcr_running) {
bool was_running = impl->is_hcr_running;
if (was_running) {
PauseHostConditionalRendering();
}
impl->conditional_resolve_pass->Resolve(*impl->hcr_resolve_buffer, to_resolve,
@ -1335,7 +1342,9 @@ void QueryCacheRuntime::HostConditionalRenderingCompareBCImpl(DAddr address, boo
impl->hcr_setup.flags = is_equal ? 0 : VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
impl->hcr_is_set = true;
impl->is_hcr_running = false;
ResumeHostConditionalRendering();
if (was_running) {
ResumeHostConditionalRendering();
}
}
bool QueryCacheRuntime::HostConditionalRenderingCompareValue(VideoCommon::LookupData object_1,

View file

@ -217,8 +217,6 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
FlushWork();
gpu_memory->FlushCaching();
query_cache.NotifySegment(true);
GraphicsPipeline* const pipeline{pipeline_cache.CurrentGraphicsPipeline()};
if (!pipeline) {
return;
@ -232,9 +230,13 @@ void RasterizerVulkan::PrepareDraw(bool is_indexed, Func&& draw_func) {
UpdateDynamicStates();
HandleTransformFeedback();
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
draw_func();
query_cache.CounterEnable(VideoCommon::QueryType::StreamingByteCount, false);
}
void RasterizerVulkan::Draw(bool is_indexed, u32 instance_count) {
@ -311,8 +313,6 @@ void RasterizerVulkan::DrawTexture() {
};
FlushWork();
query_cache.NotifySegment(true);
std::scoped_lock l{texture_cache.mutex};
texture_cache.SynchronizeGraphicsDescriptors();
texture_cache.UpdateRenderTargets(false);
@ -359,10 +359,6 @@ void RasterizerVulkan::Clear(u32 layer_count) {
FlushWork();
gpu_memory->FlushCaching();
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
auto& regs = maxwell3d->regs;
const bool use_color = regs.clear_surface.R || regs.clear_surface.G || regs.clear_surface.B ||
regs.clear_surface.A;
@ -378,6 +374,10 @@ void RasterizerVulkan::Clear(u32 layer_count) {
const VkExtent2D render_area = framebuffer->RenderArea();
scheduler.RequestRenderpass(framebuffer);
query_cache.NotifySegment(true);
query_cache.CounterEnable(VideoCommon::QueryType::ZPassPixelCount64,
maxwell3d->regs.zpass_pixel_count_enable);
u32 up_scale = 1;
u32 down_shift = 0;
if (texture_cache.IsRescaling()) {
@ -518,6 +518,14 @@ void RasterizerVulkan::DispatchCompute() {
}
const std::array<u32, 3> dim{qmd.grid_dim_x, qmd.grid_dim_y, qmd.grid_dim_z};
scheduler.RequestOutsideRenderPassOperationContext();
static constexpr VkMemoryBarrier READ_BARRIER{
.sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER,
.pNext = nullptr,
.srcAccessMask = VK_ACCESS_MEMORY_WRITE_BIT,
.dstAccessMask = VK_ACCESS_MEMORY_READ_BIT,
};
scheduler.Record([](vk::CommandBuffer cmdbuf) { cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
0, READ_BARRIER); });
scheduler.Record([dim](vk::CommandBuffer cmdbuf) { cmdbuf.Dispatch(dim[0], dim[1], dim[2]); });
}
@ -824,6 +832,7 @@ std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay(
if (!image_view) {
return {};
}
query_cache.NotifySegment(false);
const auto& resolution = Settings::values.resolution_info;
@ -935,22 +944,20 @@ void RasterizerVulkan::UpdateDynamicStates() {
UpdateDepthBounds(regs);
UpdateStencilFaces(regs);
UpdateLineWidth(regs);
// TODO: updating line stipple causes the cmdbuf to die
// UpdateLineStipple(regs);
const u8 dynamic_state = Settings::values.dyna_state.GetValue();
auto features = DynamicFeatures{
.has_extended_dynamic_state = device.IsExtExtendedDynamicStateSupported()
&& dynamic_state > 0,
.has_extended_dynamic_state_2 = device.IsExtExtendedDynamicState2Supported()
&& dynamic_state > 1,
.has_extended_dynamic_state_2_extra = device.IsExtExtendedDynamicState2ExtrasSupported()
&& dynamic_state > 1,
.has_extended_dynamic_state_3_blend = device.IsExtExtendedDynamicState3BlendingSupported()
&& dynamic_state > 2,
.has_extended_dynamic_state_3_enables = device.IsExtExtendedDynamicState3EnablesSupported()
&& dynamic_state > 2,
.has_extended_dynamic_state =
device.IsExtExtendedDynamicStateSupported() && dynamic_state > 0,
.has_extended_dynamic_state_2 =
device.IsExtExtendedDynamicState2Supported() && dynamic_state > 1,
.has_extended_dynamic_state_2_extra =
device.IsExtExtendedDynamicState2ExtrasSupported() && dynamic_state > 1,
.has_extended_dynamic_state_3_blend =
device.IsExtExtendedDynamicState3BlendingSupported() && dynamic_state > 2,
.has_extended_dynamic_state_3_enables =
device.IsExtExtendedDynamicState3EnablesSupported() && dynamic_state > 2,
.has_dynamic_vertex_input = device.IsExtVertexInputDynamicStateSupported(),
};
@ -975,16 +982,12 @@ void RasterizerVulkan::UpdateDynamicStates() {
if (features.has_extended_dynamic_state_3_enables) {
using namespace Tegra::Engines;
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE
|| device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
struct In
{
if (device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_OPEN_SOURCE ||
device.GetDriverID() == VkDriverIdKHR::VK_DRIVER_ID_AMD_PROPRIETARY) {
struct In {
const Maxwell3D::Regs::VertexAttribute::Type d;
In(Maxwell3D::Regs::VertexAttribute::Type n)
: d(n)
{}
bool operator()(Maxwell3D::Regs::VertexAttribute n) const
{
In(Maxwell3D::Regs::VertexAttribute::Type n) : d(n) {}
bool operator()(Maxwell3D::Regs::VertexAttribute n) const {
return n.type == d;
}
};
@ -1135,36 +1138,36 @@ void RasterizerVulkan::UpdateDepthBias(Tegra::Engines::Maxwell3D::Regs& regs) {
if (is_d24 && !device.SupportsD24DepthBuffer()) {
static constexpr const size_t length = sizeof(NEEDS_D24) / sizeof(NEEDS_D24[0]);
static constexpr const u64 *start = NEEDS_D24;
static constexpr const u64 *end = NEEDS_D24 + length;
static constexpr const u64* start = NEEDS_D24;
static constexpr const u64* end = NEEDS_D24 + length;
const u64 *it = std::find(start, end, program_id);
const u64* it = std::find(start, end, program_id);
if (it != end) {
// the base formulas can be obtained from here:
// https://docs.microsoft.com/en-us/windows/win32/direct3d11/d3d10-graphics-programming-guide-output-merger-stage-depth-bias
const double rescale_factor = static_cast<double>(1ULL << (32 - 24))
/ (static_cast<double>(0x1.ep+127));
const double rescale_factor =
static_cast<double>(1ULL << (32 - 24)) / (static_cast<double>(0x1.ep+127));
units = static_cast<float>(static_cast<double>(units) * rescale_factor);
}
}
scheduler.Record(
[constant = units, clamp = regs.depth_bias_clamp, factor = regs.slope_scale_depth_bias, this](
vk::CommandBuffer cmdbuf) {
if (device.IsExtDepthBiasControlSupported()) {
static VkDepthBiasRepresentationInfoEXT bias_info{
.sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT,
.pNext = nullptr,
.depthBiasRepresentation = VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT,
.depthBiasExact = VK_FALSE,
};
scheduler.Record([constant = units, clamp = regs.depth_bias_clamp,
factor = regs.slope_scale_depth_bias, this](vk::CommandBuffer cmdbuf) {
if (device.IsExtDepthBiasControlSupported()) {
static VkDepthBiasRepresentationInfoEXT bias_info{
.sType = VK_STRUCTURE_TYPE_DEPTH_BIAS_REPRESENTATION_INFO_EXT,
.pNext = nullptr,
.depthBiasRepresentation =
VK_DEPTH_BIAS_REPRESENTATION_LEAST_REPRESENTABLE_VALUE_FORCE_UNORM_EXT,
.depthBiasExact = VK_FALSE,
};
cmdbuf.SetDepthBias(constant, clamp, factor, &bias_info);
} else {
cmdbuf.SetDepthBias(constant, clamp, factor);
}
});
cmdbuf.SetDepthBias(constant, clamp, factor, &bias_info);
} else {
cmdbuf.SetDepthBias(constant, clamp, factor);
}
});
}
void RasterizerVulkan::UpdateBlendConstants(Tegra::Engines::Maxwell3D::Regs& regs) {
@ -1346,8 +1349,7 @@ void RasterizerVulkan::UpdateRasterizerDiscardEnable(Tegra::Engines::Maxwell3D::
});
}
void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs)
{
void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchConservativeRasterizationMode()) {
return;
}
@ -1359,8 +1361,7 @@ void RasterizerVulkan::UpdateConservativeRasterizationMode(Tegra::Engines::Maxwe
});
}
void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs)
{
void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs& regs) {
if (!state_tracker.TouchLineStippleEnable()) {
return;
}
@ -1370,19 +1371,7 @@ void RasterizerVulkan::UpdateLineStippleEnable(Tegra::Engines::Maxwell3D::Regs&
});
}
void RasterizerVulkan::UpdateLineStipple(Tegra::Engines::Maxwell3D::Regs& regs)
{
if (!state_tracker.TouchLineStipple()) {
return;
}
scheduler.Record([params = regs.line_stipple_params](vk::CommandBuffer cmdbuf) {
cmdbuf.SetLineStippleEXT(params.factor, static_cast<uint16_t>(params.pattern));
});
}
void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs)
{
void RasterizerVulkan::UpdateLineRasterizationMode(Tegra::Engines::Maxwell3D::Regs& regs) {
// if (!state_tracker.TouchLi()) {
// return;
// }

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -257,16 +260,6 @@ u64 Scheduler::SubmitExecution(VkSemaphore signal_semaphore, VkSemaphore wait_se
void Scheduler::AllocateNewContext() {
// Enable counters once again. These are disabled when a command buffer is finished.
if (query_cache) {
#if ANDROID
if (Settings::IsGPULevelHigh()) {
// This is problematic on Android, disable on GPU Normal.
query_cache->NotifySegment(true);
}
#else
query_cache->NotifySegment(true);
#endif
}
}
void Scheduler::InvalidateState() {
@ -276,15 +269,7 @@ void Scheduler::InvalidateState() {
}
void Scheduler::EndPendingOperations() {
#if ANDROID
if (Settings::IsGPULevelHigh()) {
// This is problematic on Android, disable on GPU Normal.
// query_cache->DisableStreams();
}
#else
// query_cache->DisableStreams();
#endif
query_cache->NotifySegment(false);
query_cache->CounterReset(VideoCommon::QueryType::ZPassPixelCount64);
EndRenderPass();
}
@ -292,6 +277,10 @@ void Scheduler::EndRenderPass() {
if (!state.renderpass) {
return;
}
query_cache->CounterEnable(VideoCommon::QueryType::ZPassPixelCount64, false);
query_cache->NotifySegment(false);
Record([num_images = num_renderpass_images, images = renderpass_images,
ranges = renderpass_image_ranges](vk::CommandBuffer cmdbuf) {
std::array<VkImageMemoryBarrier, 9> barriers;

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
@ -38,6 +41,7 @@ using VideoCommon::ImageInfo;
using VideoCommon::ImageType;
using VideoCommon::SubresourceRange;
using VideoCore::Surface::BytesPerBlock;
using VideoCore::Surface::HasAlpha;
using VideoCore::Surface::IsPixelFormatASTC;
using VideoCore::Surface::IsPixelFormatInteger;
using VideoCore::Surface::SurfaceType;
@ -1323,6 +1327,7 @@ void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, Im
case PixelFormat::D32_FLOAT_S8_UINT:
case PixelFormat::Invalid:
default:
LOG_ERROR(Render_Vulkan, "Unimplemented texture conversion from {} to {} format type", src_view.format, dst_view.format);
break;
}
}
@ -1364,6 +1369,16 @@ bool TextureCacheRuntime::IsFormatScalable(PixelFormat format) {
void TextureCacheRuntime::CopyImage(Image& dst, Image& src,
std::span<const VideoCommon::ImageCopy> copies) {
// As per the size-compatible formats section of vulkan, copy manually via ReinterpretImage
// these images that aren't size-compatible
if (BytesPerBlock(src.info.format) != BytesPerBlock(dst.info.format)) {
auto oneCopy = VideoCommon::ImageCopy{
.src_offset = VideoCommon::Offset3D(0, 0, 0),
.dst_offset = VideoCommon::Offset3D(0, 0, 0),
.extent = dst.info.size
};
return ReinterpretImage(dst, src, std::span{&oneCopy, 1});
}
boost::container::small_vector<VkImageCopy, 16> vk_copies(copies.size());
const VkImageAspectFlags aspect_mask = dst.AspectMask();
ASSERT(aspect_mask == src.AspectMask());

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: 2014 Citra Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
@ -237,6 +240,44 @@ SurfaceType GetFormatType(PixelFormat pixel_format) {
return SurfaceType::Invalid;
}
bool HasAlpha(PixelFormat pixel_format) {
switch (pixel_format) {
case PixelFormat::A8B8G8R8_UNORM:
case PixelFormat::A8B8G8R8_SNORM:
case PixelFormat::A8B8G8R8_SINT:
case PixelFormat::A8B8G8R8_UINT:
case PixelFormat::A1R5G5B5_UNORM:
case PixelFormat::A2B10G10R10_UNORM:
case PixelFormat::A2B10G10R10_UINT:
case PixelFormat::A2R10G10B10_UNORM:
case PixelFormat::A1B5G5R5_UNORM:
case PixelFormat::A5B5G5R1_UNORM:
case PixelFormat::R16G16B16A16_FLOAT:
case PixelFormat::R16G16B16A16_UNORM:
case PixelFormat::R16G16B16A16_SNORM:
case PixelFormat::R16G16B16A16_SINT:
case PixelFormat::R16G16B16A16_UINT:
case PixelFormat::R32G32B32A32_UINT:
case PixelFormat::BC1_RGBA_UNORM:
case PixelFormat::B8G8R8A8_UNORM:
case PixelFormat::R32G32B32A32_FLOAT:
case PixelFormat::R32G32B32A32_SINT:
case PixelFormat::A8B8G8R8_SRGB:
case PixelFormat::B8G8R8A8_SRGB:
case PixelFormat::BC1_RGBA_SRGB:
case PixelFormat::A4B4G4R4_UNORM:
case PixelFormat::BC2_SRGB:
case PixelFormat::BC2_UNORM:
case PixelFormat::BC3_SRGB:
case PixelFormat::BC3_UNORM:
case PixelFormat::BC7_SRGB:
case PixelFormat::BC7_UNORM:
return true;
default:
return false;
}
}
bool IsPixelFormatASTC(PixelFormat format) {
switch (format) {
case PixelFormat::ASTC_2D_4X4_UNORM:

View file

@ -503,6 +503,8 @@ PixelFormat PixelFormatFromGPUPixelFormat(Service::android::PixelFormat format);
SurfaceType GetFormatType(PixelFormat pixel_format);
bool HasAlpha(PixelFormat pixel_format);
bool IsPixelFormatASTC(PixelFormat format);
bool IsPixelFormatBCn(PixelFormat format);

View file

@ -444,7 +444,7 @@ Instance Instance::Create(u32 version, Span<const char*> layers, Span<const char
const VkApplicationInfo application_info{
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
.pNext = nullptr,
.pApplicationName = "Eden Emulator",
.pApplicationName = "yuzu Emulator",
.applicationVersion = VK_MAKE_VERSION(0, 1, 0),
.pEngineName = "Eden Emulator",
.engineVersion = VK_MAKE_VERSION(0, 1, 0),