Compare commits

...

3 commits

Author SHA1 Message Date
bbb4302adc [dynarmic] backport WAITPKG based spinlocks
All checks were successful
eden-license / license-header (pull_request) Successful in 29s
Signed-off-by: lizzie <lizzie@eden-emu.dev>
2025-10-01 03:30:14 +02:00
43a7470a7d
[Maxwell]: Fix shaders compilation memory leak (#2606)
Co-authored-by: collecting <collecting@citron-emu.org>

"The ObjectPool<Statement> was never being cleared after use. When compiling complex shaders, this would allocate gigabytes of memory, causing the emulator to run out of RAM and be killed by the operating system. This is a critical fix that prevents out-of-memory crashes on all operating systems when playing games with complex shaders."

Co-authored-by: Gamer64 <76565986+Gamer64ytb@users.noreply.github.com>
Reviewed-on: #2606
Reviewed-by: MaranBr <maranbr@eden-emu.dev>
Reviewed-by: Shinmegumi <shinmegumi@eden-emu.dev>
Co-authored-by: Gamer64 <gamer64@eden-emu.dev>
Co-committed-by: Gamer64 <gamer64@eden-emu.dev>
2025-10-01 01:21:12 +02:00
dfca07f4e3
Initial a9 (minsdk=28) support (#2600)
Minimal changes to make android 10 installable and emulationFragment not immediately crashable.
Testers (mainly android 10) NEEDED!!!

Co-authored-by: Allison Cunha <allisonbzk@gmail.com>
Reviewed-on: #2600
Reviewed-by: Lizzie <lizzie@eden-emu.dev>
Co-authored-by: xbzk <xbzk@eden-emu.dev>
Co-committed-by: xbzk <xbzk@eden-emu.dev>
2025-10-01 00:10:59 +02:00
10 changed files with 62 additions and 11 deletions

View file

@ -59,7 +59,7 @@ android {
defaultConfig {
// TODO If this is ever modified, change application_id in strings.xml
applicationId = "dev.eden.eden_emulator"
minSdk = 30
minSdk = 28
targetSdk = 36
versionName = getGitVersion()

View file

@ -19,6 +19,7 @@ import org.yuzu.yuzu_emu.adapters.GameAdapter
import androidx.core.view.doOnNextLayout
import org.yuzu.yuzu_emu.YuzuApplication
import androidx.preference.PreferenceManager
import androidx.core.view.WindowInsetsCompat
/**
* CarouselRecyclerView encapsulates all carousel logic for the games UI.
@ -205,8 +206,8 @@ class CarouselRecyclerView @JvmOverloads constructor(
if (enabled) {
useCustomDrawingOrder = true
val insets = rootWindowInsets
val bottomInset = insets?.getInsets(android.view.WindowInsets.Type.systemBars())?.bottom ?: 0
val insets = rootWindowInsets?.let { WindowInsetsCompat.toWindowInsetsCompat(it, this) }
val bottomInset = insets?.getInsets(WindowInsetsCompat.Type.systemBars())?.bottom ?: 0
val internalFactor = resources.getFraction(R.fraction.carousel_card_size_factor, 1, 1)
val userFactor = preferences.getFloat(CAROUSEL_CARD_SIZE_FACTOR, internalFactor).coerceIn(
0f,

View file

@ -56,6 +56,16 @@
#include "common/host_memory.h"
#include "common/logging/log.h"
#if defined(__ANDROID__) && __ANDROID_API__ < 30
#include <sys/syscall.h>
#ifndef MFD_CLOEXEC
#define MFD_CLOEXEC 0x0001U
#endif
static int memfd_create(const char* name, unsigned int flags) {
return syscall(__NR_memfd_create, name, flags);
}
#endif
namespace Common {
constexpr size_t PageAlignment = 0x1000;

View file

@ -188,6 +188,8 @@ HostFeature GetHostFeatures() {
features |= HostFeature::LZCNT;
if (cpu_info.has(Cpu::tGFNI))
features |= HostFeature::GFNI;
if (cpu_info.has(Cpu::tWAITPKG))
features |= HostFeature::WAITPKG;
if (cpu_info.has(Cpu::tBMI2)) {
// BMI2 instructions such as pdep and pext have been very slow up until Zen 3.

View file

@ -430,10 +430,11 @@ void AxxEmitX64::EmitExclusiveWriteMemoryInline(AxxEmitContext& ctx, IR::Inst* i
const Xbyak::Reg64 vaddr = ctx.reg_alloc.UseGpr(args[1]);
const Xbyak::Reg32 status = ctx.reg_alloc.ScratchGpr().cvt32();
const Xbyak::Reg64 tmp = ctx.reg_alloc.ScratchGpr();
const Xbyak::Reg64 tmp2 = ctx.reg_alloc.ScratchGpr();
const auto wrapped_fn = exclusive_write_fallbacks[std::make_tuple(ordered, bitsize, vaddr.getIdx(), value.getIdx())];
EmitExclusiveLock(code, conf, tmp, eax);
EmitExclusiveLock(code, conf, tmp, tmp2);
SharedLabel end = GenSharedLabel();

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
* Copyright (c) 2022 MerryMage
* SPDX-License-Identifier: 0BSD
@ -343,7 +346,7 @@ void EmitExclusiveLock(BlockOfCode& code, const UserConfig& conf, Xbyak::Reg64 p
}
code.mov(pointer, mcl::bit_cast<u64>(GetExclusiveMonitorLockPointer(conf.global_monitor)));
EmitSpinLockLock(code, pointer, tmp);
EmitSpinLockLock(code, pointer, tmp, code.HasHostFeature(HostFeature::WAITPKG));
}
template<typename UserConfig>

View file

@ -35,9 +35,10 @@ enum class HostFeature : u64 {
BMI2 = 1ULL << 19,
LZCNT = 1ULL << 20,
GFNI = 1ULL << 21,
WAITPKG = 1ULL << 22,
// Zen-based BMI2
FastBMI2 = 1ULL << 22,
FastBMI2 = 1ULL << 23,
// Orthographic AVX512 features on 128 and 256 vectors
AVX512_Ortho = AVX512F | AVX512VL,

View file

@ -22,17 +22,46 @@ static const auto default_cg_mode = nullptr; //Allow RWE
namespace Dynarmic {
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) {
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp, bool waitpkg) {
// TODO: this is because we lack regalloc - so better to be safe :(
if (waitpkg) {
code.push(Xbyak::util::eax);
code.push(Xbyak::util::ebx);
code.push(Xbyak::util::edx);
}
Xbyak::Label start, loop;
code.jmp(start, code.T_NEAR);
code.L(loop);
code.pause();
if (waitpkg) {
// TODO: This clobbers EAX and EDX did we tell the regalloc?
// ARM ptr for address-monitoring
code.umonitor(ptr);
// tmp.bit[0] = 0: C0.1 | Slow Wakup | Better Savings
// tmp.bit[0] = 1: C0.2 | Fast Wakup | Lesser Savings
// edx:eax is implicitly used as a 64-bit deadline timestamp
// Use the maximum so that we use the operating system's maximum
// allowed wait time within the IA32_UMWAIT_CONTROL register
// Enter power state designated by tmp and wait for a write to lock_ptr
code.mov(Xbyak::util::eax, 0xFFFFFFFF);
code.mov(Xbyak::util::edx, Xbyak::util::eax);
// TODO: We can only be here because tmp is 1 already - however we repeatedly overwrite it...
code.mov(Xbyak::util::ebx, 1);
code.umwait(Xbyak::util::ebx);
// CF == 1 if we hit the OS-timeout in IA32_UMWAIT_CONTROL without a write
// CF == 0 if we exited the wait for any other reason
} else {
code.pause();
}
code.L(start);
code.mov(tmp, 1);
/*code.lock();*/ code.xchg(code.dword[ptr], tmp);
code.test(tmp, tmp);
code.jnz(loop, code.T_NEAR);
if (waitpkg) {
code.pop(Xbyak::util::edx);
code.pop(Xbyak::util::ebx);
code.pop(Xbyak::util::eax);
}
}
void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp) {
@ -60,7 +89,7 @@ void SpinLockImpl::Initialize() {
code.align();
lock = code.getCurr<void (*)(volatile int*)>();
EmitSpinLockLock(code, ABI_PARAM1, code.eax);
EmitSpinLockLock(code, ABI_PARAM1, code.eax, false);
code.ret();
code.align();

View file

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
/* This file is part of the dynarmic project.
* Copyright (c) 2022 MerryMage
* SPDX-License-Identifier: 0BSD
@ -9,7 +12,7 @@
namespace Dynarmic {
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp);
void EmitSpinLockLock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp, bool waitpkg);
void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg32 tmp);
} // namespace Dynarmic

View file

@ -991,6 +991,7 @@ IR::AbstractSyntaxList BuildASL(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::
Statement& root{goto_pass.RootStatement()};
IR::AbstractSyntaxList syntax_list;
TranslatePass{inst_pool, block_pool, stmt_pool, env, root, syntax_list, host_info};
stmt_pool.ReleaseContents();
return syntax_list;
}