Browse Source

Merge remote-tracking branch 'origin/master' into overlay_fix

pull/3123/head
Maufeat 3 weeks ago
parent
commit
809eef8ce9
  1. 2
      externals/CMakeLists.txt
  2. 27
      src/common/steady_clock.cpp
  3. 5
      src/common/thread.cpp
  4. 20
      src/common/windows/timer_resolution.cpp
  5. 4
      src/core/arm/dynarmic/arm_dynarmic_32.cpp
  6. 2
      src/core/arm/dynarmic/arm_dynarmic_64.cpp
  7. 7
      src/dynarmic/CMakeLists.txt
  8. 8
      src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp
  9. 8
      src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp
  10. 28
      src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp
  11. 35
      src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp
  12. 12
      src/video_core/macro/macro_jit_x64.cpp

2
externals/CMakeLists.txt

@ -27,7 +27,7 @@ set_directory_properties(PROPERTIES EXCLUDE_FROM_ALL ON)
# Xbyak (also used by Dynarmic, so needs to be added first) # Xbyak (also used by Dynarmic, so needs to be added first)
if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64) if (ARCHITECTURE_x86 OR ARCHITECTURE_x86_64)
if (PLATFORM_SUN OR PLATFORM_OPENBSD)
if (PLATFORM_SUN OR PLATFORM_OPENBSD OR PLATFORM_NETBSD OR PLATFORM_DRAGONFLY)
AddJsonPackage(xbyak_sun) AddJsonPackage(xbyak_sun)
else() else()
AddJsonPackage(xbyak) AddJsonPackage(xbyak)

27
src/common/steady_clock.cpp

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -25,15 +28,21 @@ static s64 WindowsQueryPerformanceCounter() {
} }
static s64 GetSystemTimeNS() { static s64 GetSystemTimeNS() {
// GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
static constexpr s64 Multiplier = 100;
// Convert Windows epoch to Unix epoch.
static constexpr s64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
FILETIME filetime;
GetSystemTimePreciseAsFileTime(&filetime);
return Multiplier * ((static_cast<s64>(filetime.dwHighDateTime) << 32) +
static_cast<s64>(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
static auto pf = (decltype(&GetSystemTimePreciseAsFileTime))(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "GetSystemTimePreciseAsFileTime"); // Windows 8+
if (pf) {
// GetSystemTimePreciseAsFileTime returns the file time in 100ns units.
constexpr s64 Multiplier = 100;
// Convert Windows epoch to Unix epoch.
constexpr s64 WindowsEpochToUnixEpoch = 0x19DB1DED53E8000LL;
FILETIME filetime;
pf(&filetime);
return Multiplier * ((s64(filetime.dwHighDateTime) << 32) + s64(filetime.dwLowDateTime) - WindowsEpochToUnixEpoch);
} else {
// Only Windows XP and below error out here
LARGE_INTEGER ticks;
QueryPerformanceCounter(&ticks);
return ticks.QuadPart;
}
} }
#endif #endif

5
src/common/thread.cpp

@ -81,10 +81,9 @@ void SetCurrentThreadPriority(ThreadPriority new_priority) {
// Sets the debugger-visible name of the current thread. // Sets the debugger-visible name of the current thread.
void SetCurrentThreadName(const char* name) { void SetCurrentThreadName(const char* name) {
if (auto pf = (decltype(&SetThreadDescription))(void*)GetProcAddress(GetModuleHandle(TEXT("KernelBase.dll")), "SetThreadDescription"); pf)
static auto pf = (decltype(&SetThreadDescription))(void*)GetProcAddress(GetModuleHandle(TEXT("KernelBase.dll")), "SetThreadDescription");
if (pf)
pf(GetCurrentThread(), UTF8ToUTF16W(name).data()); // Windows 10+ pf(GetCurrentThread(), UTF8ToUTF16W(name).data()); // Windows 10+
else
; // No-op
} }
#else // !MSVC_VER, so must be POSIX threads #else // !MSVC_VER, so must be POSIX threads

20
src/common/windows/timer_resolution.cpp

@ -1,3 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
@ -62,14 +65,15 @@ TimerResolution GetTimerResolution() {
void SetHighQoS() { void SetHighQoS() {
// https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service // https://learn.microsoft.com/en-us/windows/win32/procthread/quality-of-service
PROCESS_POWER_THROTTLING_STATE PowerThrottling{
.Version{PROCESS_POWER_THROTTLING_CURRENT_VERSION},
.ControlMask{PROCESS_POWER_THROTTLING_EXECUTION_SPEED |
PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION},
.StateMask{},
};
SetProcessInformation(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling,
sizeof(PROCESS_POWER_THROTTLING_STATE));
static auto pf = (decltype(&SetProcessInformation))(void*)GetProcAddress(GetModuleHandle(TEXT("Kernel32.dll")), "SetProcessInformation");
if (pf) {
PROCESS_POWER_THROTTLING_STATE PowerThrottling{
.Version = PROCESS_POWER_THROTTLING_CURRENT_VERSION,
.ControlMask = PROCESS_POWER_THROTTLING_EXECUTION_SPEED | PROCESS_POWER_THROTTLING_IGNORE_TIMER_RESOLUTION,
.StateMask = 0,
};
pf(GetCurrentProcess(), ProcessPowerThrottling, &PowerThrottling, sizeof(PROCESS_POWER_THROTTLING_STATE)); // Windows 7+
}
} }
} // Anonymous namespace } // Anonymous namespace

4
src/core/arm/dynarmic/arm_dynarmic_32.cpp

@ -211,7 +211,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
config.enable_cycle_counting = !m_uses_wall_clock; config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size // Code cache size
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
#if defined(ARCHITECTURE_arm64) || defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
config.code_cache_size = std::uint32_t(128_MiB); config.code_cache_size = std::uint32_t(128_MiB);
#else #else
config.code_cache_size = std::uint32_t(512_MiB); config.code_cache_size = std::uint32_t(512_MiB);
@ -295,7 +295,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ArmDynarmic32::MakeJit(Common::PageTable* pa
// Curated optimizations // Curated optimizations
case Settings::CpuAccuracy::Auto: case Settings::CpuAccuracy::Auto:
config.unsafe_optimizations = true; config.unsafe_optimizations = true;
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__)
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__sun__) || defined(__HAIKU__) || defined(__DragonFly__) || defined(__NetBSD__)
config.fastmem_pointer = std::nullopt; config.fastmem_pointer = std::nullopt;
config.fastmem_exclusive_access = false; config.fastmem_exclusive_access = false;
#endif #endif

2
src/core/arm/dynarmic/arm_dynarmic_64.cpp

@ -270,7 +270,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ArmDynarmic64::MakeJit(Common::PageTable* pa
config.enable_cycle_counting = !m_uses_wall_clock; config.enable_cycle_counting = !m_uses_wall_clock;
// Code cache size // Code cache size
#if defined(ARCHITECTURE_arm64) || defined(__sun__)
#if defined(ARCHITECTURE_arm64) || defined(__sun__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__OpenBSD__)
config.code_cache_size = std::uint32_t(128_MiB); config.code_cache_size = std::uint32_t(128_MiB);
#else #else
config.code_cache_size = std::uint32_t(512_MiB); config.code_cache_size = std::uint32_t(512_MiB);

7
src/dynarmic/CMakeLists.txt

@ -18,7 +18,12 @@ endif()
# Dynarmic project options # Dynarmic project options
option(DYNARMIC_ENABLE_CPU_FEATURE_DETECTION "Turning this off causes dynarmic to assume the host CPU doesn't support anything later than SSE3" ON) option(DYNARMIC_ENABLE_CPU_FEATURE_DETECTION "Turning this off causes dynarmic to assume the host CPU doesn't support anything later than SSE3" ON)
option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${PLATFORM_OPENBSD})
if (PLATFORM_OPENBSD OR PLATFORM_DRAGONFLY OR PLATFORM_NETBSD)
set(REQUIRE_WX ON)
else()
set(REQUIRE_WX OFF)
endif()
option(DYNARMIC_ENABLE_NO_EXECUTE_SUPPORT "Enables support for systems that require W^X" ${REQUIRE_WX})
option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" OFF) option(DYNARMIC_IGNORE_ASSERTS "Ignore asserts" OFF)
option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF) option(DYNARMIC_TESTS_USE_UNICORN "Enable fuzzing tests against unicorn" OFF)

8
src/dynarmic/src/dynarmic/backend/x64/a32_emit_x64.cpp

@ -87,9 +87,11 @@ A32EmitX64::A32EmitX64(BlockOfCode& code, A32::UserConfig conf, A32::Jit* jit_in
code.PreludeComplete(); code.PreludeComplete();
ClearFastDispatchTable(); ClearFastDispatchTable();
exception_handler.SetFastmemCallback([this](u64 rip_) {
return FastmemCallback(rip_);
});
if (conf.fastmem_pointer.has_value()) {
exception_handler.SetFastmemCallback([this](u64 rip_) {
return FastmemCallback(rip_);
});
}
} }
A32EmitX64::~A32EmitX64() = default; A32EmitX64::~A32EmitX64() = default;

8
src/dynarmic/src/dynarmic/backend/x64/a64_emit_x64.cpp

@ -61,9 +61,11 @@ A64EmitX64::A64EmitX64(BlockOfCode& code, A64::UserConfig conf, A64::Jit* jit_in
code.PreludeComplete(); code.PreludeComplete();
ClearFastDispatchTable(); ClearFastDispatchTable();
exception_handler.SetFastmemCallback([this](u64 rip_) {
return FastmemCallback(rip_);
});
if (conf.fastmem_pointer.has_value()) {
exception_handler.SetFastmemCallback([this](u64 rip_) {
return FastmemCallback(rip_);
});
}
} }
A64EmitX64::~A64EmitX64() = default; A64EmitX64::~A64EmitX64() = default;

28
src/dynarmic/src/dynarmic/backend/x64/block_of_code.cpp

@ -87,18 +87,24 @@ public:
// Waste a page to store the size // Waste a page to store the size
size += DYNARMIC_PAGE_SIZE; size += DYNARMIC_PAGE_SIZE;
# if defined(MAP_ANONYMOUS)
int mode = MAP_PRIVATE | MAP_ANONYMOUS;
# elif defined(MAP_ANON)
int mode = MAP_PRIVATE | MAP_ANON;
# else
# error "not supported"
# endif
# ifdef MAP_JIT
int mode = MAP_PRIVATE;
#if defined(MAP_ANONYMOUS)
mode |= MAP_ANONYMOUS;
#elif defined(MAP_ANON)
mode |= MAP_ANON;
#else
# error "not supported"
#endif
#ifdef MAP_JIT
mode |= MAP_JIT; mode |= MAP_JIT;
# endif
void* p = mmap(nullptr, size, PROT_READ | PROT_WRITE, mode, -1, 0);
#endif
int prot = PROT_READ | PROT_WRITE;
#ifdef PROT_MPROTECT
// https://man.netbsd.org/mprotect.2 specifies that an mprotect() that is LESS
// restrictive than the original mapping MUST fail
prot |= PROT_MPROTECT(PROT_READ) | PROT_MPROTECT(PROT_WRITE) | PROT_MPROTECT(PROT_EXEC);
#endif
void* p = mmap(nullptr, size, prot, mode, -1, 0);
if (p == MAP_FAILED) { if (p == MAP_FAILED) {
using Xbyak::Error; using Xbyak::Error;
XBYAK_THROW(Xbyak::ERR_CANT_ALLOC); XBYAK_THROW(Xbyak::ERR_CANT_ALLOC);

35
src/dynarmic/src/dynarmic/common/spin_lock_x64.cpp

@ -7,7 +7,7 @@
*/ */
#include <mutex> #include <mutex>
#include <optional>
#include <xbyak/xbyak.h> #include <xbyak/xbyak.h>
#include "dynarmic/backend/x64/abi.h" #include "dynarmic/backend/x64/abi.h"
@ -42,43 +42,46 @@ void EmitSpinLockUnlock(Xbyak::CodeGenerator& code, Xbyak::Reg64 ptr, Xbyak::Reg
} }
namespace { namespace {
struct SpinLockImpl { struct SpinLockImpl {
void Initialize();
void Initialize() noexcept;
static void GlobalInitialize() noexcept;
Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096, default_cg_mode); Xbyak::CodeGenerator code = Xbyak::CodeGenerator(4096, default_cg_mode);
void (*lock)(volatile int*);
void (*unlock)(volatile int*);
void (*lock)(volatile int*) = nullptr;
void (*unlock)(volatile int*) = nullptr;
}; };
std::once_flag flag; std::once_flag flag;
SpinLockImpl impl;
void SpinLockImpl::Initialize() {
const Xbyak::Reg64 ABI_PARAM1 = Backend::X64::HostLocToReg64(Backend::X64::ABI_PARAM1);
/// @brief Bear in mind that initializing the variable as-is on ctor time will trigger bugs
/// because some OSes do not prepare mprotect() properly at static ctor time
/// We can't really do anything about it, so just live with this fact
std::optional<SpinLockImpl> impl;
void SpinLockImpl::Initialize() noexcept {
Xbyak::Reg64 const ABI_PARAM1 = Backend::X64::HostLocToReg64(Backend::X64::ABI_PARAM1);
code.align(); code.align();
lock = code.getCurr<void (*)(volatile int*)>(); lock = code.getCurr<void (*)(volatile int*)>();
EmitSpinLockLock(code, ABI_PARAM1, code.eax); EmitSpinLockLock(code, ABI_PARAM1, code.eax);
code.ret(); code.ret();
code.align(); code.align();
unlock = code.getCurr<void (*)(volatile int*)>(); unlock = code.getCurr<void (*)(volatile int*)>();
EmitSpinLockUnlock(code, ABI_PARAM1, code.eax); EmitSpinLockUnlock(code, ABI_PARAM1, code.eax);
code.ret(); code.ret();
} }
void SpinLockImpl::GlobalInitialize() noexcept {
impl.emplace();
impl->Initialize();
}
} // namespace } // namespace
void SpinLock::Lock() noexcept { void SpinLock::Lock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.lock(&storage);
std::call_once(flag, &SpinLockImpl::GlobalInitialize);
impl->lock(&storage);
} }
void SpinLock::Unlock() noexcept { void SpinLock::Unlock() noexcept {
std::call_once(flag, &SpinLockImpl::Initialize, impl);
impl.unlock(&storage);
std::call_once(flag, &SpinLockImpl::GlobalInitialize);
impl->unlock(&storage);
} }
} // namespace Dynarmic } // namespace Dynarmic

12
src/video_core/macro/macro_jit_x64.cpp

@ -44,10 +44,20 @@ std::bitset<32> PersistentCallerSavedRegs() {
return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED; return PERSISTENT_REGISTERS & Common::X64::ABI_ALL_CALLER_SAVED;
} }
/// @brief Must enforce W^X constraints, as we yet don't havea global "NO_EXECUTE" support flag
/// the speed loss is minimal, and in fact may be negligible, however for your peace of mind
/// I simply included known OSes whom had W^X issues
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
static const auto default_cg_mode = Xbyak::DontSetProtectRWE;
#else
static const auto default_cg_mode = nullptr; //Allow RWE
#endif
class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro { class MacroJITx64Impl final : public Xbyak::CodeGenerator, public CachedMacro {
public: public:
explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector<u32>& code_) explicit MacroJITx64Impl(Engines::Maxwell3D& maxwell3d_, const std::vector<u32>& code_)
: CodeGenerator{MAX_CODE_SIZE}, code{code_}, maxwell3d{maxwell3d_} {
: Xbyak::CodeGenerator(MAX_CODE_SIZE, default_cg_mode)
, code{code_}, maxwell3d{maxwell3d_} {
Compile(); Compile();
} }

Loading…
Cancel
Save