mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-10-05 15:52:45 +02:00
texture_cache: Improve SD865
Means games like Minecraft Dungeons, Sea of Stars, Luigi Mansion 2, Astroneer, etc are now playable. It also cleans up the recent abi.cpp and bindless texture commits a bit. Everything is in #ifdef ANDROID - The biggest change is CACHING_PAGEBITS = 12. Without that the way the buffercache grows and joins buffers can cause Android to run out of memory (as you end up with just one big buffer that needs to be copied every time it grows)
This commit is contained in:
@@ -116,18 +116,13 @@ void ABI_PopCallerSaveRegistersAndAdjustStack(BlockOfCode& code, const std::size
|
||||
ABI_PopRegistersAndAdjustStack(code, frame_size, ABI_ALL_CALLER_SAVE);
|
||||
}
|
||||
|
||||
static consteval size_t ABI_AllCallerSaveSize() noexcept {
|
||||
return ABI_ALL_CALLER_SAVE.max_size();
|
||||
}
|
||||
static consteval std::array<HostLoc, ABI_AllCallerSaveSize() - 1> ABI_AllCallerSaveExcept(const std::size_t except) noexcept {
|
||||
std::array<HostLoc, ABI_AllCallerSaveSize() - 1> arr;
|
||||
for(std::size_t i = 0; i < arr.size(); ++i) {
|
||||
arr[i] = static_cast<HostLoc>(i + (i >= except ? 1 : 0));
|
||||
}
|
||||
static std::vector<HostLoc> ABI_AllCallerSaveExcept(const std::size_t except) noexcept {
|
||||
std::vector<HostLoc> arr;
|
||||
std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(arr), static_cast<HostLoc>(except));
|
||||
return arr;
|
||||
}
|
||||
|
||||
alignas(64) static constinit std::array<HostLoc, ABI_AllCallerSaveSize() - 1> ABI_CALLER_SAVED_EXCEPT_TABLE[32] = {
|
||||
alignas(64) static std::vector<HostLoc> ABI_CALLER_SAVED_EXCEPT_TABLE[32] = {
|
||||
ABI_AllCallerSaveExcept(0),
|
||||
ABI_AllCallerSaveExcept(1),
|
||||
ABI_AllCallerSaveExcept(2),
|
||||
@@ -163,24 +158,12 @@ alignas(64) static constinit std::array<HostLoc, ABI_AllCallerSaveSize() - 1> AB
|
||||
};
|
||||
|
||||
void ABI_PushCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) {
|
||||
#ifdef _MSC_VER
|
||||
std::vector<HostLoc> regs;
|
||||
std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception);
|
||||
ABI_PushRegistersAndAdjustStack(code, 0, regs);
|
||||
#else
|
||||
ASSUME(size_t(exception) < 32);
|
||||
ABI_PushRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]);
|
||||
#endif
|
||||
}
|
||||
|
||||
void ABI_PopCallerSaveRegistersAndAdjustStackExcept(BlockOfCode& code, const HostLoc exception) {
|
||||
#ifdef _MSC_VER
|
||||
std::vector<HostLoc> regs;
|
||||
std::remove_copy(ABI_ALL_CALLER_SAVE.begin(), ABI_ALL_CALLER_SAVE.end(), std::back_inserter(regs), exception);
|
||||
ABI_PopRegistersAndAdjustStack(code, 0, regs);
|
||||
#else
|
||||
ASSUME(size_t(exception) < 32);
|
||||
ABI_PopRegistersAndAdjustStack(code, 0, ABI_CALLER_SAVED_EXCEPT_TABLE[size_t(exception)]);
|
||||
#endif
|
||||
}
|
||||
} // namespace Dynarmic::Backend::X64
|
||||
|
@@ -151,7 +151,12 @@ static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestConte
|
||||
// For now, ignore options, which are in input buffer 1 for GetHostByNameRequestWithOptions.
|
||||
|
||||
// Prevent resolution of Nintendo servers
|
||||
if (host.find("srv.nintendo.net") != std::string::npos) {
|
||||
if (host.find("srv.nintendo.net") != std::string::npos ||
|
||||
host.find("battle.net") != std::string::npos ||
|
||||
host.find("microsoft.com") != std::string::npos ||
|
||||
host.find("mojang.com") != std::string::npos ||
|
||||
host.find("xboxlive.com") != std::string::npos ||
|
||||
host.find("minecraftservices.com") != std::string::npos) {
|
||||
LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
|
||||
return {0, GetAddrInfoError::AGAIN};
|
||||
}
|
||||
@@ -268,7 +273,12 @@ static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext
|
||||
const std::string host = Common::StringFromBuffer(host_buffer);
|
||||
|
||||
// Prevent resolution of Nintendo servers
|
||||
if (host.find("srv.nintendo.net") != std::string::npos) {
|
||||
if (host.find("srv.nintendo.net") != std::string::npos ||
|
||||
host.find("battle.net") != std::string::npos ||
|
||||
host.find("microsoft.com") != std::string::npos ||
|
||||
host.find("mojang.com") != std::string::npos ||
|
||||
host.find("xboxlive.com") != std::string::npos ||
|
||||
host.find("minecraftservices.com") != std::string::npos) {
|
||||
LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
|
||||
return {0, GetAddrInfoError::AGAIN};
|
||||
}
|
||||
|
@@ -1,9 +1,13 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#include "common/bit_field.h"
|
||||
#include "common/common_types.h"
|
||||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
||||
#include <fstream>
|
||||
|
||||
namespace Shader::Maxwell {
|
||||
namespace {
|
||||
@@ -33,6 +37,17 @@ enum class ShuffleMode : u64 {
|
||||
}
|
||||
}
|
||||
|
||||
bool IsKONA() {
|
||||
std::ifstream machineFile("/sys/devices/soc0/machine");
|
||||
if (machineFile.is_open()) {
|
||||
std::string line;
|
||||
std::getline(machineFile, line);
|
||||
if (line == "KONA")
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32& mask) {
|
||||
union {
|
||||
u64 insn;
|
||||
@@ -44,7 +59,10 @@ void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32
|
||||
|
||||
const IR::U32 result{ShuffleOperation(v.ir, v.X(shfl.src_reg), index, mask, shfl.mode)};
|
||||
v.ir.SetPred(shfl.pred, v.ir.GetInBoundsFromOp(result));
|
||||
v.X(shfl.dest_reg, result);
|
||||
if (IsKONA())
|
||||
v.X(shfl.dest_reg, v.ir.Imm32(0xffffffff)); // This fixes the freeze for Retroid / Snapdragon SD865
|
||||
else
|
||||
v.X(shfl.dest_reg, result);
|
||||
}
|
||||
} // Anonymous namespace
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2021 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
@@ -327,30 +330,14 @@ std::optional<ConstBufferAddr> TryGetConstBuffer(const IR::Inst* inst, Environme
|
||||
};
|
||||
}
|
||||
|
||||
// TODO:xbzk: shall be dropped when Track method cover all bindless stuff
|
||||
static ConstBufferAddr last_valid_addr = ConstBufferAddr{
|
||||
.index = 0,
|
||||
.offset = 0,
|
||||
.shift_left = 0,
|
||||
.secondary_index = 0,
|
||||
.secondary_offset = 0,
|
||||
.secondary_shift_left = 0,
|
||||
.dynamic_offset = {},
|
||||
.count = 1,
|
||||
.has_secondary = false,
|
||||
};
|
||||
|
||||
TextureInst MakeInst(Environment& env, IR::Block* block, IR::Inst& inst) {
|
||||
ConstBufferAddr addr;
|
||||
ConstBufferAddr addr{};
|
||||
if (IsBindless(inst)) {
|
||||
const std::optional<ConstBufferAddr> track_addr{Track(inst.Arg(0), env)};
|
||||
|
||||
if (!track_addr) {
|
||||
//throw NotImplementedException("Failed to track bindless texture constant buffer");
|
||||
addr = last_valid_addr; // TODO:xbzk: shall be dropped when Track method cover all bindless stuff
|
||||
LOG_WARNING(Shader, "Failed to track bindless texture constant buffer");
|
||||
} else {
|
||||
addr = *track_addr;
|
||||
last_valid_addr = addr; // TODO:xbzk: shall be dropped when Track method cover all bindless stuff
|
||||
}
|
||||
} else {
|
||||
addr = ConstBufferAddr{
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -42,6 +45,8 @@ BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R
|
||||
critical_memory = static_cast<u64>(
|
||||
std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||
DEFAULT_CRITICAL_MEMORY));
|
||||
|
||||
LOG_INFO(Render_Vulkan, "BufferCache - device_local_memory: {} minimum_memory: {} critical_memory: {}", device_local_memory, minimum_memory, critical_memory);
|
||||
}
|
||||
|
||||
template <class P>
|
||||
@@ -50,7 +55,7 @@ BufferCache<P>::~BufferCache() = default;
|
||||
template <class P>
|
||||
void BufferCache<P>::RunGarbageCollector() {
|
||||
const bool aggressive_gc = total_used_memory >= critical_memory;
|
||||
const u64 ticks_to_destroy = aggressive_gc ? 60 : 120;
|
||||
const u64 ticks_to_destroy = aggressive_gc ? 60 : 150;
|
||||
int num_iterations = aggressive_gc ? 64 : 32;
|
||||
const auto clean_up = [this, &num_iterations](BufferId buffer_id) {
|
||||
if (num_iterations == 0) {
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -156,7 +159,11 @@ template <class P>
|
||||
class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInfo> {
|
||||
// Page size for caching purposes.
|
||||
// This is unrelated to the CPU page size and it can be changed as it seems optimal.
|
||||
#ifdef ANDROID
|
||||
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;
|
||||
@@ -170,9 +177,15 @@ class BufferCache : public VideoCommon::ChannelSetupCaches<BufferCacheChannelInf
|
||||
static constexpr bool SEPARATE_IMAGE_BUFFERS_BINDINGS = P::SEPARATE_IMAGE_BUFFER_BINDINGS;
|
||||
static constexpr bool USE_MEMORY_MAPS_FOR_UPLOADS = P::USE_MEMORY_MAPS_FOR_UPLOADS;
|
||||
|
||||
#ifdef ANDROID
|
||||
static constexpr s64 DEFAULT_EXPECTED_MEMORY = 512_MiB;
|
||||
static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB;
|
||||
static constexpr s64 TARGET_THRESHOLD = 3_GiB;
|
||||
#else
|
||||
static constexpr s64 DEFAULT_EXPECTED_MEMORY = 512_MiB;
|
||||
static constexpr s64 DEFAULT_CRITICAL_MEMORY = 1_GiB;
|
||||
static constexpr s64 TARGET_THRESHOLD = 4_GiB;
|
||||
#endif
|
||||
|
||||
// Debug Flags.
|
||||
|
||||
@@ -448,7 +461,12 @@ private:
|
||||
Tegra::MaxwellDeviceMemoryManager& device_memory;
|
||||
|
||||
Common::SlotVector<Buffer> slot_buffers;
|
||||
DelayedDestructionRing<Buffer, 8> delayed_destruction_ring;
|
||||
#ifdef ANDROID
|
||||
static constexpr size_t TICKS_TO_DESTROY = 6;
|
||||
#else
|
||||
static constexpr size_t TICKS_TO_DESTROY = 8;
|
||||
#endif
|
||||
DelayedDestructionRing<Buffer, TICKS_TO_DESTROY> delayed_destruction_ring;
|
||||
|
||||
const Tegra::Engines::DrawManager::IndirectParams* current_draw_indirect{};
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: Ryujinx Team and Contributors
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
@@ -20,6 +23,9 @@ CDmaPusher::CDmaPusher(Host1x::Host1x& host1x_, s32 id)
|
||||
: host1x{host1x_}, memory_manager{host1x.GMMU()},
|
||||
host_processor{std::make_unique<Host1x::Control>(host1x_)}, current_class{
|
||||
static_cast<ChClassId>(id)} {
|
||||
#ifdef ANDROID
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds{500}); // HACK: Fix for Astroneer - doesn't always start without this delay. Happens on Windows too (but rarer)
|
||||
#endif
|
||||
thread = std::jthread([this](std::stop_token stop_token) { ProcessEntries(stop_token); });
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 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
|
||||
|
||||
@@ -137,6 +140,7 @@ void Layer::CreateStagingBuffer(const Tegra::FramebufferConfig& framebuffer) {
|
||||
.pQueueFamilyIndices = nullptr,
|
||||
};
|
||||
|
||||
buffer.reset();
|
||||
buffer = memory_allocator.CreateBuffer(ci, MemoryUsage::Upload);
|
||||
}
|
||||
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -63,6 +66,8 @@ TextureCache<P>::TextureCache(Runtime& runtime_, Tegra::MaxwellDeviceMemoryManag
|
||||
std::max(std::min(device_local_memory - min_vacancy_critical, min_spacing_critical),
|
||||
DEFAULT_CRITICAL_MEMORY));
|
||||
minimum_memory = static_cast<u64>((device_local_memory - mem_threshold) / 2);
|
||||
|
||||
LOG_INFO(Render_Vulkan, "TextureCache - device_local_memory:{} minimum_memory: {} critical_memory: {} expected_memory: {}", device_local_memory, minimum_memory, critical_memory, expected_memory);
|
||||
} else {
|
||||
expected_memory = DEFAULT_EXPECTED_MEMORY + 512_MiB;
|
||||
critical_memory = DEFAULT_CRITICAL_MEMORY + 1_GiB;
|
||||
@@ -78,6 +83,9 @@ void TextureCache<P>::RunGarbageCollector() {
|
||||
size_t num_iterations = 0;
|
||||
|
||||
const auto Configure = [&](bool allow_aggressive) {
|
||||
#ifdef ANDROID
|
||||
high_priority_mode = true;
|
||||
#endif
|
||||
high_priority_mode = total_used_memory >= expected_memory;
|
||||
aggressive_mode = allow_aggressive && total_used_memory >= critical_memory;
|
||||
ticks_to_destroy = aggressive_mode ? 10ULL : high_priority_mode ? 25ULL : 50ULL;
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
// SPDX-FileCopyrightText: 2023 yuzu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
@@ -107,10 +110,17 @@ class TextureCache : public VideoCommon::ChannelSetupCaches<TextureCacheChannelI
|
||||
|
||||
static constexpr size_t UNSET_CHANNEL{std::numeric_limits<size_t>::max()};
|
||||
|
||||
#ifdef ANDROID
|
||||
static constexpr s64 TARGET_THRESHOLD = 3_GiB;
|
||||
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;
|
||||
#else
|
||||
static constexpr s64 TARGET_THRESHOLD = 4_GiB;
|
||||
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;
|
||||
#endif
|
||||
|
||||
using Runtime = typename P::Runtime;
|
||||
using Image = typename P::Image;
|
||||
@@ -476,7 +486,11 @@ private:
|
||||
};
|
||||
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
|
||||
|
||||
#ifdef ANDROID
|
||||
static constexpr size_t TICKS_TO_DESTROY = 5;
|
||||
#else
|
||||
static constexpr size_t TICKS_TO_DESTROY = 8;
|
||||
#endif
|
||||
DelayedDestructionRing<Image, TICKS_TO_DESTROY> sentenced_images;
|
||||
DelayedDestructionRing<ImageView, TICKS_TO_DESTROY> sentenced_image_view;
|
||||
DelayedDestructionRing<Framebuffer, TICKS_TO_DESTROY> sentenced_framebuffers;
|
||||
|
@@ -1,3 +1,6 @@
|
||||
// SPDX-FileCopyrightText: 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
|
||||
|
||||
@@ -268,7 +271,10 @@ vk::Buffer MemoryAllocator::CreateBuffer(const VkBufferCreateInfo& ci, MemoryUsa
|
||||
VmaAllocation allocation{};
|
||||
VkMemoryPropertyFlags property_flags{};
|
||||
|
||||
vk::Check(vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info));
|
||||
VkResult result = vmaCreateBuffer(allocator, &ci, &alloc_ci, &handle, &allocation, &alloc_info);
|
||||
if (result == VK_ERROR_OUT_OF_DEVICE_MEMORY) {
|
||||
LOG_ERROR(Render_Vulkan, "Out of memory creating buffer (size: {})", ci.size);
|
||||
}
|
||||
vmaGetAllocationMemoryProperties(allocator, allocation, &property_flags);
|
||||
|
||||
u8* data = reinterpret_cast<u8*>(alloc_info.pMappedData);
|
||||
|
Reference in New Issue
Block a user