mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2026-08-15 21:19:47 +00:00
a27d35463e
This simplifies the GPU accuracy setting by removing the intermediate Balanced mode and setting High as the default on desktop platforms. It introduces a dedicated setting for GPU fence behavior, allowing the synchronization policy to be configured independently of GPU accuracy. The Vulkan buffer cache now tracks GPU recording timeline ticks and waits only when necessary, reducing unnecessary synchronization while maintaining correctness for hard-to-trace graphical bugs. GPU buffer readback has also been refined to synchronize only the affected upload regions when needed, and default DMA behavior has been updated to align with the new GPU accuracy model. ### TL;DR The fix for particles freezing and unfreezing in mid-air in `Super Mario Odyssey` has been improved, resulting in less of a performance hit. This game requires the new `Enable GPU Buffer Readback` option to be enabled to fix this issue. The vertex explosions that occurred in `Super Mario Bros. Wonder`, especially in World 4, have been completely eliminated. You can now enjoy a smooth experience without graphical glitches exploding across the screen. This game requires the new `GPU Fence Behavior` option to be set to `Strict` to fully fix this issue. The flickering issue inside certain Shrines in `The Legend of Zelda: Tears of the Kingdom` has also been fixed. For now, this game requires the new `GPU Fence Behavior` option to be set to `Accurate` to fully fix this issue. These options are intended to fix graphical bugs in games that require better synchronization behavior between CPU and GPU, so other games may be affected as well. Co-authored-by: xbzk <xbzk@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4182 Reviewed-by: Lizzie <lizzie@eden-emu.dev>
227 lines
9.5 KiB
C++
227 lines
9.5 KiB
C++
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
// SPDX-FileCopyrightText: Copyright 2024 Torzu 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
|
|
|
|
#pragma once
|
|
|
|
#include <string>
|
|
#include <string_view>
|
|
#include <utility>
|
|
#include <vector>
|
|
#include "common/common_types.h"
|
|
|
|
namespace Settings {
|
|
|
|
template <typename T>
|
|
struct EnumMetadata {
|
|
static std::vector<std::pair<std::string_view, T>> Canonicalizations();
|
|
static u32 Index();
|
|
static T GetFirst();
|
|
static T GetLast();
|
|
};
|
|
|
|
#define PAIR_45(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_46(N, __VA_ARGS__))
|
|
#define PAIR_44(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_45(N, __VA_ARGS__))
|
|
#define PAIR_43(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_44(N, __VA_ARGS__))
|
|
#define PAIR_42(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_43(N, __VA_ARGS__))
|
|
#define PAIR_41(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_42(N, __VA_ARGS__))
|
|
#define PAIR_40(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_41(N, __VA_ARGS__))
|
|
#define PAIR_39(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_40(N, __VA_ARGS__))
|
|
#define PAIR_38(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_39(N, __VA_ARGS__))
|
|
#define PAIR_37(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_38(N, __VA_ARGS__))
|
|
#define PAIR_36(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_37(N, __VA_ARGS__))
|
|
#define PAIR_35(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_36(N, __VA_ARGS__))
|
|
#define PAIR_34(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_35(N, __VA_ARGS__))
|
|
#define PAIR_33(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_34(N, __VA_ARGS__))
|
|
#define PAIR_32(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_33(N, __VA_ARGS__))
|
|
#define PAIR_31(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_32(N, __VA_ARGS__))
|
|
#define PAIR_30(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_31(N, __VA_ARGS__))
|
|
#define PAIR_29(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_30(N, __VA_ARGS__))
|
|
#define PAIR_28(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_29(N, __VA_ARGS__))
|
|
#define PAIR_27(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_28(N, __VA_ARGS__))
|
|
#define PAIR_26(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_27(N, __VA_ARGS__))
|
|
#define PAIR_25(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_26(N, __VA_ARGS__))
|
|
#define PAIR_24(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_25(N, __VA_ARGS__))
|
|
#define PAIR_23(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_24(N, __VA_ARGS__))
|
|
#define PAIR_22(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_23(N, __VA_ARGS__))
|
|
#define PAIR_21(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_22(N, __VA_ARGS__))
|
|
#define PAIR_20(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_21(N, __VA_ARGS__))
|
|
#define PAIR_19(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_20(N, __VA_ARGS__))
|
|
#define PAIR_18(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_19(N, __VA_ARGS__))
|
|
#define PAIR_17(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_18(N, __VA_ARGS__))
|
|
#define PAIR_16(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_17(N, __VA_ARGS__))
|
|
#define PAIR_15(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_16(N, __VA_ARGS__))
|
|
#define PAIR_14(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_15(N, __VA_ARGS__))
|
|
#define PAIR_13(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_14(N, __VA_ARGS__))
|
|
#define PAIR_12(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_13(N, __VA_ARGS__))
|
|
#define PAIR_11(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_12(N, __VA_ARGS__))
|
|
#define PAIR_10(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_11(N, __VA_ARGS__))
|
|
#define PAIR_9(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_10(N, __VA_ARGS__))
|
|
#define PAIR_8(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_9(N, __VA_ARGS__))
|
|
#define PAIR_7(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_8(N, __VA_ARGS__))
|
|
#define PAIR_6(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_7(N, __VA_ARGS__))
|
|
#define PAIR_5(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_6(N, __VA_ARGS__))
|
|
#define PAIR_4(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_5(N, __VA_ARGS__))
|
|
#define PAIR_3(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_4(N, __VA_ARGS__))
|
|
#define PAIR_2(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_3(N, __VA_ARGS__))
|
|
#define PAIR_1(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_2(N, __VA_ARGS__))
|
|
#define PAIR(N, X, ...) {#X, N::X} __VA_OPT__(, PAIR_1(N, __VA_ARGS__))
|
|
|
|
#define PP_HEAD(A, ...) A
|
|
|
|
#define ENUM(NAME, ...) \
|
|
enum class NAME : u32 { __VA_ARGS__ }; \
|
|
template<> inline std::vector<std::pair<std::string_view, NAME>> EnumMetadata<NAME>::Canonicalizations() { \
|
|
return {PAIR(NAME, __VA_ARGS__)}; \
|
|
} \
|
|
template<> inline u32 EnumMetadata<NAME>::Index() { \
|
|
return __COUNTER__; \
|
|
} \
|
|
template<> inline NAME EnumMetadata<NAME>::GetFirst() { \
|
|
return NAME::PP_HEAD(__VA_ARGS__); \
|
|
} \
|
|
template<> inline NAME EnumMetadata<NAME>::GetLast() { \
|
|
return (std::vector<std::pair<std::string_view, NAME>>{PAIR(NAME, __VA_ARGS__)}).back().second; \
|
|
}
|
|
|
|
// AudioEngine must be specified discretely due to having existing but slightly different
|
|
// canonicalizations
|
|
// TODO (lat9nq): Remove explicit definition of AudioEngine/sink_id
|
|
enum class AudioEngine : u32 { Auto, Cubeb, Sdl3, Null, Oboe, };
|
|
template<>
|
|
inline std::vector<std::pair<std::string_view, AudioEngine>> EnumMetadata<AudioEngine>::Canonicalizations() {
|
|
return {
|
|
{"auto", AudioEngine::Auto},
|
|
{"cubeb", AudioEngine::Cubeb},
|
|
{"sdl3", AudioEngine::Sdl3},
|
|
{"null", AudioEngine::Null}, {"oboe", AudioEngine::Oboe},
|
|
};
|
|
}
|
|
/// @brief This is just a sufficiently large number that is more than the number of other enums declared here
|
|
template<>
|
|
inline u32 EnumMetadata<AudioEngine>::Index() {
|
|
return 100;
|
|
}
|
|
template<>
|
|
inline AudioEngine EnumMetadata<AudioEngine>::GetFirst() {
|
|
return AudioEngine::Auto;
|
|
}
|
|
template<>
|
|
inline AudioEngine EnumMetadata<AudioEngine>::GetLast() {
|
|
return AudioEngine::Oboe;
|
|
}
|
|
|
|
ENUM(AudioMode, Mono, Stereo, Surround);
|
|
//static_assert(EnumMetadata<AudioMode>::GetFirst() == AudioMode::Mono);
|
|
//static_assert(EnumMetadata<AudioMode>::GetLast() == AudioMode::Surround);
|
|
|
|
ENUM(Language, Japanese, EnglishAmerican, French, German, Italian, Spanish, Chinese, Korean, Dutch,
|
|
Portuguese, Russian, Taiwanese, EnglishBritish, FrenchCanadian, SpanishLatin,
|
|
ChineseSimplified, ChineseTraditional, PortugueseBrazilian, Polish, Thai);
|
|
ENUM(Region, Japan, Usa, Europe, Australia, China, Korea, Taiwan);
|
|
ENUM(TimeZone, Auto, Default, Cet, Cst6Cdt, Cuba, Eet, Egypt, Eire, Est, Est5Edt, Gb, GbEire, Gmt,
|
|
GmtPlusZero, GmtMinusZero, GmtZero, Greenwich, Hongkong, Hst, Iceland, Iran, Israel, Jamaica,
|
|
Japan, Kwajalein, Libya, Met, Mst, Mst7Mdt, Navajo, Nz, NzChat, Poland, Portugal, Prc, Pst8Pdt,
|
|
Roc, Rok, Singapore, Turkey, Uct, Universal, Utc, WSu, Wet, Zulu);
|
|
ENUM(AnisotropyMode, Automatic, Default, X2, X4, X8, X16, X32, X64, None);
|
|
ENUM(AstcDecodeMode, Cpu, Gpu, CpuAsynchronous);
|
|
ENUM(AstcRecompression, Uncompressed, Bc1, Bc3);
|
|
ENUM(FramePacingMode, Target_Auto, Target_30, Target_60, Target_90, Target_120);
|
|
ENUM(VSyncMode, Immediate, Mailbox, Fifo, FifoRelaxed);
|
|
ENUM(VramUsageMode, Conservative, Aggressive);
|
|
ENUM(RendererBackend, OpenGL_GLSL, Vulkan, Null, OpenGL_GLASM, OpenGL_SPIRV);
|
|
ENUM(GpuAccuracy, Low, High);
|
|
ENUM(DmaAccuracy, Default, Unsafe, Safe);
|
|
ENUM(GpuFenceBehavior, Default, Immediate, Balanced, Accurate, Strict);
|
|
ENUM(CpuBackend, Dynarmic, Nce);
|
|
ENUM(CpuAccuracy, Auto, Accurate, Unsafe, Paranoid, Debugging);
|
|
ENUM(CpuClock, Off, Boost, Fast)
|
|
ENUM(MemoryLayout, Memory_4Gb, Memory_6Gb, Memory_8Gb, Memory_10Gb, Memory_12Gb);
|
|
ENUM(ConfirmStop, Ask_Always, Ask_Based_On_Game, Ask_Never);
|
|
ENUM(FullscreenMode, Borderless, Exclusive);
|
|
ENUM(NvdecEmulation, Off, Cpu, Gpu);
|
|
ENUM(ResolutionSetup, Res1_4X, Res1_2X, Res3_4X, Res1X, Res5_4X, Res3_2X, Res2X, Res3X, Res4X, Res5X, Res6X, Res7X, Res8X);
|
|
ENUM(ScalingFilter, NearestNeighbor, Bilinear, Bicubic, Gaussian, Lanczos, ScaleForce, Fsr, Area, ZeroTangent, BSpline, Mitchell, Spline1, Mmpx, Sgsr, SgsrEdge);
|
|
ENUM(AntiAliasing, None, Fxaa, Smaa);
|
|
ENUM(AspectRatio, R16_9, R4_3, R21_9, R16_10, Stretch);
|
|
ENUM(ConsoleMode, Handheld, Docked);
|
|
ENUM(AppletMode, HLE, LLE);
|
|
ENUM(SpirvOptimizeMode, Never, OnLoad, Always);
|
|
ENUM(GpuOverclock, Normal, Medium, High)
|
|
ENUM(GpuUnswizzleSize, VerySmall, Small, Normal, Large, VeryLarge)
|
|
ENUM(GpuUnswizzle, VeryLow, Low, Normal, Medium, High)
|
|
ENUM(GpuUnswizzleChunk, VeryLow, Low, Normal, Medium, High)
|
|
ENUM(TemperatureUnits, Celsius, Fahrenheit)
|
|
ENUM(ExtendedDynamicState, Disabled, EDS1, EDS2, EDS3);
|
|
ENUM(GpuLogLevel, Off, Errors, Standard, Verbose, All)
|
|
ENUM(GameListMode, TreeView, GridView, CarouselView);
|
|
ENUM(SpeedMode, Standard, Turbo, Slow);
|
|
|
|
template <typename Type>
|
|
inline std::string_view CanonicalizeEnum(Type id) {
|
|
const auto group = EnumMetadata<Type>::Canonicalizations();
|
|
for (auto& [name, value] : group)
|
|
if (value == id)
|
|
return name;
|
|
return "unknown";
|
|
}
|
|
|
|
template <typename Type>
|
|
inline Type ToEnum(const std::string& canonicalization) {
|
|
const auto group = EnumMetadata<Type>::Canonicalizations();
|
|
for (auto& [name, value] : group)
|
|
if (name == canonicalization)
|
|
return value;
|
|
return {};
|
|
}
|
|
} // namespace Settings
|
|
|
|
#undef ENUM
|
|
#undef PAIR
|
|
#undef PAIR_1
|
|
#undef PAIR_2
|
|
#undef PAIR_3
|
|
#undef PAIR_4
|
|
#undef PAIR_5
|
|
#undef PAIR_6
|
|
#undef PAIR_7
|
|
#undef PAIR_8
|
|
#undef PAIR_9
|
|
#undef PAIR_10
|
|
#undef PAIR_12
|
|
#undef PAIR_13
|
|
#undef PAIR_14
|
|
#undef PAIR_15
|
|
#undef PAIR_16
|
|
#undef PAIR_17
|
|
#undef PAIR_18
|
|
#undef PAIR_19
|
|
#undef PAIR_20
|
|
#undef PAIR_22
|
|
#undef PAIR_23
|
|
#undef PAIR_24
|
|
#undef PAIR_25
|
|
#undef PAIR_26
|
|
#undef PAIR_27
|
|
#undef PAIR_28
|
|
#undef PAIR_29
|
|
#undef PAIR_30
|
|
#undef PAIR_32
|
|
#undef PAIR_33
|
|
#undef PAIR_34
|
|
#undef PAIR_35
|
|
#undef PAIR_36
|
|
#undef PAIR_37
|
|
#undef PAIR_38
|
|
#undef PAIR_39
|
|
#undef PAIR_40
|
|
#undef PAIR_42
|
|
#undef PAIR_43
|
|
#undef PAIR_44
|
|
#undef PAIR_45
|