diff --git a/CMakeLists.txt b/CMakeLists.txt index 7f192887f7..f436c0a183 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -227,6 +227,8 @@ endif() # TODO(crueter): CI this? option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) +option(YUZU_LEGACY "Apply patches that improve compatibility with older GPUs (e.g. Snapdragon 865) at the cost of performance" OFF) + cmake_dependent_option(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) cmake_dependent_option(YUZU_ROOM_STANDALONE "Enable standalone room executable" ON "YUZU_ROOM" OFF) @@ -324,6 +326,11 @@ if (UNIX) add_compile_definitions(YUZU_UNIX=1) endif() +if (YUZU_LEGACY) + message(WARNING "Making legacy build. Performance may suffer.") + add_compile_definitions(YUZU_LEGACY) +endif() + if (ARCHITECTURE_arm64 AND (ANDROID OR PLATFORM_LINUX)) set(HAS_NCE 1) add_compile_definitions(HAS_NCE=1) diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index e8d8141711..c85da039cb 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -57,8 +57,8 @@ android { } defaultConfig { - // TODO If this is ever modified, change application_id in strings.xml applicationId = "dev.eden.eden_emulator" + minSdk = 28 targetSdk = 36 versionName = getGitVersion() @@ -72,8 +72,30 @@ android { buildConfigField("String", "GIT_HASH", "\"${getGitHash()}\"") buildConfigField("String", "BRANCH", "\"${getBranch()}\"") + + externalNativeBuild { + cmake { + arguments.addAll(listOf( + "-DENABLE_QT=0", // Don't use QT + "-DENABLE_SDL2=0", // Don't use SDL + "-DENABLE_WEB_SERVICE=1", // Enable web service + "-DENABLE_OPENSSL=ON", + "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work + "-DYUZU_USE_CPM=ON", + "-DCPMUTIL_FORCE_BUNDLED=ON", + "-DYUZU_USE_BUNDLED_FFMPEG=ON", + "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", + "-DBUILD_TESTING=OFF", + "-DYUZU_TESTS=OFF", + "-DDYNARMIC_TESTS=OFF" + )) + + abiFilters("arm64-v8a") + } + } } + val keystoreFile = System.getenv("ANDROID_KEYSTORE_FILE") signingConfigs { if (keystoreFile != null) { @@ -94,7 +116,6 @@ android { // Define build types, which are orthogonal to product flavors. buildTypes { - // Signed by release key, allowing for upload to Play Store. release { signingConfig = if (keystoreFile != null) { @@ -103,7 +124,6 @@ android { signingConfigs.getByName("default") } - resValue("string", "app_name_suffixed", "Eden") isMinifyEnabled = true isDebuggable = false proguardFiles( @@ -116,7 +136,6 @@ android { // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. register("relWithDebInfo") { isDefault = true - resValue("string", "app_name_suffixed", "Eden Debug Release") signingConfig = signingConfigs.getByName("default") isDebuggable = true proguardFiles( @@ -132,7 +151,6 @@ android { // Attaches 'debug' suffix to version and package name, allowing installation alongside the release build. debug { signingConfig = signingConfigs.getByName("default") - resValue("string", "app_name_suffixed", "Eden Debug") isDebuggable = true isJniDebuggable = true versionNameSuffix = "-debug" @@ -140,19 +158,62 @@ android { } } + // this is really annoying but idk any other ways to fix this behavior + applicationVariants.all { + val variant = this + when { + variant.flavorName == "legacy" && variant.buildType.name == "debug" -> { + variant.resValue("string", "app_name_suffixed", "Eden Legacy Debug") + } + variant.flavorName == "mainline" && variant.buildType.name == "debug" -> { + variant.resValue("string", "app_name_suffixed", "Eden Debug") + } + variant.flavorName == "genshinSpoof" && variant.buildType.name == "debug" -> { + variant.resValue("string", "app_name_suffixed", "Eden Optimized Debug") + } + variant.flavorName == "legacy" && variant.buildType.name == "relWithDebInfo" -> { + variant.resValue("string", "app_name_suffixed", "Eden Legacy Debug Release") + } + variant.flavorName == "mainline" && variant.buildType.name == "relWithDebInfo" -> { + variant.resValue("string", "app_name_suffixed", "Eden Debug Release") + } + variant.flavorName == "genshinSpoof" && variant.buildType.name == "relWithDebInfo" -> { + variant.resValue("string", "app_name_suffixed", "Eden Optimized Debug Release") + } + } + } + android { flavorDimensions.add("version") productFlavors { create("mainline") { dimension = "version" - // No need to set applicationId here + resValue("string", "app_name_suffixed", "Eden") } create("genshinSpoof") { dimension = "version" - resValue("string", "app_name_suffixed", "Eden Optimised") + resValue("string", "app_name_suffixed", "Eden Optimized") applicationId = "com.miHoYo.Yuanshen" } + + create("legacy") { + dimension = "version" + resValue("string", "app_name_suffixed", "Eden Legacy") + applicationId = "dev.legacy.eden_emulator" + + externalNativeBuild { + cmake { + arguments.add("-DYUZU_LEGACY=ON") + } + } + + sourceSets { + getByName("legacy") { + res.srcDirs("src/main/legacy") + } + } + } } } @@ -162,29 +223,6 @@ android { path = file("../../../CMakeLists.txt") } } - - defaultConfig { - externalNativeBuild { - cmake { - arguments( - "-DENABLE_QT=0", // Don't use QT - "-DENABLE_SDL2=0", // Don't use SDL - "-DENABLE_WEB_SERVICE=1", // Enable web service - "-DENABLE_OPENSSL=ON", - "-DANDROID_ARM_NEON=true", // cryptopp requires Neon to work - "-DYUZU_USE_CPM=ON", - "-DCPMUTIL_FORCE_BUNDLED=ON", - "-DYUZU_USE_BUNDLED_FFMPEG=ON", - "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", - "-DBUILD_TESTING=OFF", - "-DYUZU_TESTS=OFF", - "-DDYNARMIC_TESTS=OFF" - ) - - abiFilters("arm64-v8a") - } - } - } } tasks.register("ktlintReset", fun Delete.() { diff --git a/src/android/app/src/main/legacy/drawable/ic_icon_bg.png b/src/android/app/src/main/legacy/drawable/ic_icon_bg.png new file mode 100644 index 0000000000..3327014f8f Binary files /dev/null and b/src/android/app/src/main/legacy/drawable/ic_icon_bg.png differ diff --git a/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png b/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png new file mode 100644 index 0000000000..a9fc55a4f5 Binary files /dev/null and b/src/android/app/src/main/legacy/drawable/ic_icon_bg_orig.png differ diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index 877e8ac3c7..0e0d72fc8a 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -227,7 +227,7 @@ HaltReason ArmNce::RunThread(Kernel::KThread* thread) { if (auto it = post_handlers.find(m_guest_ctx.pc); it != post_handlers.end()) { hr = ReturnToRunCodeByTrampoline(thread_params, &m_guest_ctx, it->second); } else { - hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params); + hr = ReturnToRunCodeByExceptionLevelChange(m_thread_id, thread_params); // Android: Use "process handle SIGUSR2 -n true -p true -s false" (and SIGURG) in LLDB when debugging } // Critical section for thread cleanup diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 6f6e0c23a8..5223afe937 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -26,7 +26,9 @@ BufferCache

::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R void(slot_buffers.insert(runtime, NullBufferParams{})); gpu_modified_ranges.Clear(); inline_buffer_id = NULL_BUFFER_ID; - +#ifdef YUZU_LEGACY + immediately_free = (Settings::values.vram_usage_mode.GetValue() == Settings::VramUsageMode::Aggressive); +#endif if (!runtime.CanReportMemoryUsage()) { minimum_memory = DEFAULT_EXPECTED_MEMORY; critical_memory = DEFAULT_CRITICAL_MEMORY; @@ -1378,6 +1380,10 @@ void BufferCache

::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, }); new_buffer.MarkUsage(copies[0].dst_offset, copies[0].size); runtime.CopyBuffer(new_buffer, overlap, copies, true); +#ifdef YUZU_LEGACY + if (immediately_free) + runtime.Finish(); +#endif DeleteBuffer(overlap_id, true); } @@ -1668,7 +1674,12 @@ void BufferCache

::DeleteBuffer(BufferId buffer_id, bool do_not_mark) { } Unregister(buffer_id); - delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id])); + +#ifdef YUZU_LEGACY + if (!do_not_mark || !immediately_free) +#endif + delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id])); + slot_buffers.erase(buffer_id); if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { diff --git a/src/video_core/buffer_cache/buffer_cache_base.h b/src/video_core/buffer_cache/buffer_cache_base.h index a45e9b35f1..486d19fb79 100644 --- a/src/video_core/buffer_cache/buffer_cache_base.h +++ b/src/video_core/buffer_cache/buffer_cache_base.h @@ -154,7 +154,11 @@ template class BufferCache : public VideoCommon::ChannelSetupCaches { // Page size for caching purposes. // This is unrelated to the CPU page size and it can be changed as it seems optimal. +#ifdef YUZU_LEGACY + static constexpr u32 CACHING_PAGEBITS = 12; +#else static constexpr u32 CACHING_PAGEBITS = 16; +#endif static constexpr u64 CACHING_PAGESIZE = u64{1} << CACHING_PAGEBITS; static constexpr bool IS_OPENGL = P::IS_OPENGL; @@ -168,9 +172,14 @@ class BufferCache : public VideoCommon::ChannelSetupCaches slot_buffers; - DelayedDestructionRing delayed_destruction_ring; +#ifdef YUZU_LEGACY + static constexpr size_t TICKS_TO_DESTROY = 6; +#else + static constexpr size_t TICKS_TO_DESTROY = 8; +#endif + DelayedDestructionRing delayed_destruction_ring; const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{}; @@ -478,6 +492,9 @@ private: u64 minimum_memory = 0; u64 critical_memory = 0; BufferId inline_buffer_id; +#ifdef YUZU_LEGACY + bool immediately_free = false; +#endif std::array> CACHING_PAGEBITS)> page_table; Common::ScratchBuffer tmp_buffer; diff --git a/src/video_core/host1x/host1x.cpp b/src/video_core/host1x/host1x.cpp index 293bca6d79..cec5104144 100644 --- a/src/video_core/host1x/host1x.cpp +++ b/src/video_core/host1x/host1x.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -18,9 +21,15 @@ Host1x::~Host1x() = default; void Host1x::StartDevice(s32 fd, ChannelType type, u32 syncpt) { switch (type) { case ChannelType::NvDec: +#ifdef YUZU_LEGACY + std::call_once(nvdec_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer +#endif devices[fd] = std::make_unique(*this, fd, syncpt, frame_queue); break; case ChannelType::VIC: +#ifdef YUZU_LEGACY + std::call_once(vic_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer +#endif devices[fd] = std::make_unique(*this, fd, syncpt, frame_queue); break; default: diff --git a/src/video_core/host1x/host1x.h b/src/video_core/host1x/host1x.h index 8debac93dd..4eea214ec6 100644 --- a/src/video_core/host1x/host1x.h +++ b/src/video_core/host1x/host1x.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2021 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -201,6 +204,10 @@ private: std::unique_ptr> allocator; FrameQueue frame_queue; std::unordered_map> devices; +#ifdef YUZU_LEGACY + std::once_flag nvdec_first_init; + std::once_flag vic_first_init; +#endif }; } // namespace Tegra::Host1x diff --git a/src/video_core/texture_cache/texture_cache_base.h b/src/video_core/texture_cache/texture_cache_base.h index f7d22afde2..01a9a6a3f1 100644 --- a/src/video_core/texture_cache/texture_cache_base.h +++ b/src/video_core/texture_cache/texture_cache_base.h @@ -110,7 +110,12 @@ class TextureCache : public VideoCommon::ChannelSetupCaches::max)()}; +#ifdef YUZU_LEGACY + static constexpr s64 TARGET_THRESHOLD = 3_GiB; +#else static constexpr s64 TARGET_THRESHOLD = 4_GiB; +#endif + static constexpr s64 DEFAULT_EXPECTED_MEMORY = 1_GiB + 125_MiB; static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB + 625_MiB; static constexpr size_t GC_EMERGENCY_COUNTS = 2; @@ -479,7 +484,11 @@ private: }; Common::LeastRecentlyUsedCache lru_cache; + #ifdef YUZU_LEGACY + static constexpr size_t TICKS_TO_DESTROY = 6; + #else static constexpr size_t TICKS_TO_DESTROY = 8; +#endif DelayedDestructionRing sentenced_images; DelayedDestructionRing sentenced_image_view; DelayedDestructionRing sentenced_framebuffers; diff --git a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp index f0309117bf..4cd3442d97 100644 --- a/src/video_core/vulkan_common/vulkan_memory_allocator.cpp +++ b/src/video_core/vulkan_common/vulkan_memory_allocator.cpp @@ -325,4 +325,6 @@ namespace Vulkan { return MemoryCommit(allocator, a, info); } + + } // namespace Vulkan