Compare commits

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

10 commits
master ... test

Author SHA1 Message Date
6eef072842 test 2025-09-08 21:41:50 -06:00
81de509814 test 2025-09-08 19:51:45 -06:00
2dd76e9f7a Legacy VMA: remove memory alignment, it's pointless and wastes RAM 2025-09-07 09:59:36 -06:00
062a1a9b1a
Fix conflicts after new VMA, restore some lost fixes for A6XX (#387)
All checks were successful
eden-license / license-header (pull_request) Successful in 26s
There were a lot of a duplicate definitions and conflicts after the new VMA changes in master.
All of them were removed and/or deduplicated.
Some A6XX-specific fixes that would have been lost in translation have been restored.

Reviewed-on: #387
Reviewed-by: crueter <crueter@eden-emu.dev>
Co-authored-by: Calchan <denis.dupeyron@gmail.com>
Co-committed-by: Calchan <denis.dupeyron@gmail.com>
2025-09-05 19:43:35 +02:00
c0ebe85a74
Revert forced warp shuffle to fix some games (#385)
All checks were successful
eden-license / license-header (pull_request) Successful in 26s
Metroid Prime Remastered, Prince of Persia The Lost Crown, and maybe
some others.

A few testers and I couldn't find any game that this broke, but it fixed these two above and they said they got fewer artifacts from a few others.

Reviewed-on: #385
Reviewed-by: crueter <crueter@eden-emu.dev>
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Co-authored-by: Calchan <denis.dupeyron@gmail.com>
Co-committed-by: Calchan <denis.dupeyron@gmail.com>
2025-09-05 16:08:35 +02:00
Bix
21433675e4 [Android] Change App background to white]
All checks were successful
eden-license / license-header (pull_request) Successful in 26s
2025-09-05 00:21:29 +01:00
Bixthefin
b9c5a49546 [Android] Change app_name to Eden Legacy 2025-09-05 00:21:29 +01:00
Bixthefin
cd8cf317fb [android] Update applicationId to legacy 2025-09-05 00:21:29 +01:00
Bix
84b8e7bd50 revert cd394fc40f
revert revert [android] Snapdragon 865 patches (#23)

revert [android] Snapdragon 865 patches (#23)

Co-authored-by: Aleksandr Popovich <alekpopo@pm.me>
Reviewed-on: https://git.bixed.xyz/Bix/eden/pulls/23

Reverted due to heavy performance hits on Android with higher specifications, will be adjusted to be included in a specific build for older A6XX devices, as 855, 860, 865, 870, meanwhile it does fix critical issues with certain games crashing due to memory and VRAM usage, hits performance on SoC that can do it without this special flags.
2025-09-05 00:21:29 +01:00
Bix
010dde41eb Added "Legacy " to App name on android.
Signed-off-by: Bix <bix@bixed.xyz>
2025-09-05 00:20:48 +01:00
11 changed files with 106 additions and 20 deletions

View file

@ -58,7 +58,7 @@ android {
defaultConfig {
// TODO If this is ever modified, change application_id in strings.xml
applicationId = "dev.eden.eden_emulator"
applicationId = "dev.legacy.eden_emulator"
minSdk = 30
targetSdk = 36
versionName = getGitVersion()
@ -103,7 +103,7 @@ android {
signingConfigs.getByName("default")
}
resValue("string", "app_name_suffixed", "Eden")
resValue("string", "app_name_suffixed", "Eden Legacy")
isMinifyEnabled = true
isDebuggable = false
proguardFiles(

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 438 KiB

Before After
Before After

View file

@ -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

View file

@ -53,6 +53,16 @@ enum class NetDbError : s32 {
NoData = 4,
};
const std::vector<std::string> blockedDomains = {"srv.nintendo.net", "battle.net",
"microsoft.com", "mojang.com",
"xboxlive.com", "minecraftservices.com"};
static bool IsBlockedHost(const std::string& host) {
return std::any_of(
blockedDomains.begin(), blockedDomains.end(),
[&host](const std::string& domain) { return host.find(domain) != std::string::npos; });
}
static NetDbError GetAddrInfoErrorToNetDbError(GetAddrInfoError result) {
// These combinations have been verified on console (but are not
// exhaustive).
@ -154,7 +164,7 @@ 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 (IsBlockedHost(host)) {
LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
return {0, GetAddrInfoError::AGAIN};
}
@ -271,7 +281,7 @@ 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 (IsBlockedHost(host)) {
LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
return {0, GetAddrInfoError::AGAIN};
}
@ -359,5 +369,4 @@ void SFDNSRES::ResolverSetOptionRequest(HLERequestContext& ctx) {
rb.Push(ResultSuccess);
rb.Push<s32>(0); // bsd errno
}
} // namespace Service::Sockets

View file

@ -26,7 +26,9 @@ BufferCache<P>::BufferCache(Tegra::MaxwellDeviceMemoryManager& device_memory_, R
void(slot_buffers.insert(runtime, NullBufferParams{}));
gpu_modified_ranges.Clear();
inline_buffer_id = NULL_BUFFER_ID;
#ifdef ANDROID
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;
@ -1381,6 +1383,8 @@ void BufferCache<P>::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);
if (immediately_free)
runtime.Finish();
DeleteBuffer(overlap_id, true);
}
@ -1671,7 +1675,9 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id, bool do_not_mark) {
}
Unregister(buffer_id);
delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
if (!do_not_mark || !immediately_free)
delayed_destruction_ring.Push(std::move(slot_buffers[buffer_id]));
slot_buffers.erase(buffer_id);
if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) {

View file

@ -154,7 +154,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;
@ -168,9 +172,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.
@ -446,7 +456,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{};
@ -478,6 +493,7 @@ private:
u64 minimum_memory = 0;
u64 critical_memory = 0;
BufferId inline_buffer_id;
bool immediately_free = false;
std::array<BufferId, ((1ULL << 34) >> CACHING_PAGEBITS)> page_table;
Common::ScratchBuffer<u8> tmp_buffer;

View file

@ -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,11 @@ Host1x::~Host1x() = default;
void Host1x::StartDevice(s32 fd, ChannelType type, u32 syncpt) {
switch (type) {
case ChannelType::NvDec:
std::call_once(nvdec_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer
devices[fd] = std::make_unique<Tegra::Host1x::Nvdec>(*this, fd, syncpt, frame_queue);
break;
case ChannelType::VIC:
std::call_once(vic_first_init, []() {std::this_thread::sleep_for(std::chrono::milliseconds{500});}); // HACK: For Astroneer
devices[fd] = std::make_unique<Tegra::Host1x::Vic>(*this, fd, syncpt, frame_queue);
break;
default:

View file

@ -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,8 @@ private:
std::unique_ptr<Common::FlatAllocator<u32, 0, 32>> allocator;
FrameQueue frame_queue;
std::unordered_map<s32, std::unique_ptr<CDmaPusher>> devices;
std::once_flag nvdec_first_init;
std::once_flag vic_first_init;
};
} // namespace Tegra::Host1x

View file

@ -110,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;
@ -479,7 +486,11 @@ private:
};
Common::LeastRecentlyUsedCache<LRUItemParams> lru_cache;
#ifdef ANDROID
static constexpr size_t TICKS_TO_DESTROY = 6;
#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;

View file

@ -759,16 +759,16 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
functions.vkGetDeviceProcAddr = dld.vkGetDeviceProcAddr;
VmaAllocatorCreateFlags flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT;
if (extensions.memory_budget) {
if (extensions.memory_budget && !is_qualcomm && !is_turnip) {
flags |= VMA_ALLOCATOR_CREATE_EXT_MEMORY_BUDGET_BIT;
}
const VmaAllocatorCreateInfo allocator_info{
.flags = flags,
.physicalDevice = physical,
.device = *logical,
.preferredLargeHeapBlockSize = is_integrated
? (64u * 1024u * 1024u)
: (256u * 1024u * 1024u),
.preferredLargeHeapBlockSize = (is_qualcomm || is_turnip)
? (256u * 1024u * 1024u) // Use larger blocks for Adreno GPUs
: (is_integrated ? (64u * 1024u * 1024u) : (256u * 1024u * 1024u)),
.pAllocationCallbacks = nullptr,
.pDeviceMemoryCallbacks = nullptr,
.pHeapSizeLimit = nullptr,

View file

@ -196,6 +196,21 @@ namespace Vulkan {
}
});
}
// Additional workarounds for Adreno GPUs to avoid VMA fragmentation
const bool is_adreno = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
device.GetDriverID() == VK_DRIVER_ID_MESA_TURNIP);
if (is_adreno) {
using namespace Common::Literals;
for (u32 t = 0; t < properties.memoryTypeCount; ++t) {
const auto& memory_type = properties.memoryTypes[t];
const auto& heap = properties.memoryHeaps[memory_type.heapIndex];
// Skip memory types from heaps smaller than 512MB to reduce fragmentation
if (heap.size < 512_MiB) {
valid_memory_types &= ~(1u << t);
}
}
}
}
MemoryAllocator::~MemoryAllocator() = default;
@ -253,30 +268,42 @@ namespace Vulkan {
MemoryCommit MemoryAllocator::Commit(const VkMemoryRequirements &reqs, MemoryUsage usage)
{
// Ensure 4KB alignment for all Adreno GPUs
VkMemoryRequirements adjusted_reqs = reqs;
const bool is_adreno = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
device.GetDriverID() == VK_DRIVER_ID_MESA_TURNIP);
if (is_adreno) {
adjusted_reqs.size = Common::AlignUp(reqs.size, 4096);
}
const auto vma_usage = MemoryUsageVma(usage);
VmaAllocationCreateInfo ci{};
ci.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage);
ci.flags = MemoryUsageVmaFlags(usage);
// Skip budget constraints for Adreno GPUs to avoid fragmentation issues
if (!is_adreno) {
ci.flags |= VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
}
ci.usage = vma_usage;
ci.memoryTypeBits = reqs.memoryTypeBits & valid_memory_types;
ci.memoryTypeBits = adjusted_reqs.memoryTypeBits & valid_memory_types;
ci.requiredFlags = 0;
ci.preferredFlags = MemoryUsagePreferredVmaFlags(usage);
VmaAllocation a{};
VmaAllocationInfo info{};
VkResult res = vmaAllocateMemory(allocator, &reqs, &ci, &a, &info);
VkResult res = vmaAllocateMemory(allocator, &adjusted_reqs, &ci, &a, &info);
if (res != VK_SUCCESS) {
// Relax 1: drop budget constraint
auto ci2 = ci;
ci2.flags &= ~VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
res = vmaAllocateMemory(allocator, &reqs, &ci2, &a, &info);
res = vmaAllocateMemory(allocator, &adjusted_reqs, &ci2, &a, &info);
// Relax 2: if we preferred DEVICE_LOCAL, drop that preference
if (res != VK_SUCCESS && (ci.preferredFlags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)) {
auto ci3 = ci2;
ci3.preferredFlags &= ~VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT;
res = vmaAllocateMemory(allocator, &reqs, &ci3, &a, &info);
res = vmaAllocateMemory(allocator, &adjusted_reqs, &ci3, &a, &info);
}
}
@ -285,11 +312,16 @@ namespace Vulkan {
}
MemoryCommit MemoryAllocator::Commit(const vk::Buffer &buffer, MemoryUsage usage) {
// Allocate memory appropriate for this buffer automatically
const auto vma_usage = MemoryUsageVma(usage);
const bool is_adreno = (device.GetDriverID() == VK_DRIVER_ID_QUALCOMM_PROPRIETARY ||
device.GetDriverID() == VK_DRIVER_ID_MESA_TURNIP);
VmaAllocationCreateInfo ci{};
ci.flags = VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT | MemoryUsageVmaFlags(usage);
ci.flags = MemoryUsageVmaFlags(usage);
// Skip budget constraints for Adreno GPUs to avoid fragmentation issues
if (!is_adreno) {
ci.flags |= VMA_ALLOCATION_CREATE_WITHIN_BUDGET_BIT;
}
ci.usage = vma_usage;
ci.requiredFlags = 0;
ci.preferredFlags = MemoryUsagePreferredVmaFlags(usage);
@ -322,4 +354,6 @@ namespace Vulkan {
return MemoryCommit(allocator, a, info);
}
} // namespace Vulkan