diff options
| author | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
|---|---|---|
| committer | rdenno <rhysdenno@gmail.com> | 2026-11-02 09:26:01 -0500 |
| commit | 2786bdf580e41bf0ba6e2a6452db73c4f5b97ed2 (patch) | |
| tree | 2c59cf5d66b869af52f338f3dea6e679e590f7bb /src/common/host_memory.cpp | |
| parent | 7ac108e2571d7cb39585c58994524131dd9d8c22 (diff) | |
| parent | c0cb3325e22756edb65c87d33ef298349ade0ad3 (diff) | |
Merge branch 'nx2-experimental' into fix/hw-shader-lowering
nx2-experimental lowers partial-mask TXD as well (Splatoon Raiders).
Keep its RZ second destination and this branch's odd register for a
lone third channel; take its wider F2I mode check with the .H1 source.
Assisted-by: Claude Opus 5.5 (conflict resolution)
Diffstat (limited to 'src/common/host_memory.cpp')
| -rw-r--r-- | src/common/host_memory.cpp | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index b724bed1bd..2ef1982cbc 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp @@ -51,6 +51,7 @@ #endif // ^^^ POSIX ^^^ +#include <cstdlib> #include <mutex> #include <random> @@ -518,6 +519,14 @@ public: , virtual_size{virtual_size_} {} +#ifdef __linux__ + bool PunchHole(size_t offset, size_t length) { + return fd >= 0 && + fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, static_cast<off_t>(offset), + static_cast<off_t>(length)) == 0; + } +#endif + bool Init() { long page_size = sysconf(_SC_PAGESIZE); ASSERT_MSG(page_size == 0x1000, "page size {:#x} is incompatible with 4K paging", page_size); @@ -827,6 +836,13 @@ void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 f // Fresh backing memory is zero and the host gives it no RAM until it's touched: clear only // the granules that may hold data (title 1's heap made the host commit every page of it). // A granule cleared in full is zero again. +#ifdef __linux__ + // Handing a whole granule back to the kernel frees its RAM; a memset would commit it. + static const bool punch = [] { + const char* value = std::getenv("EDEN_PUNCH_HOLE"); + return value == nullptr || value[0] != '0'; + }(); +#endif const size_t end = physical_offset + length; for (size_t offset = physical_offset; offset < end;) { const size_t index = offset >> GranuleShift; @@ -834,8 +850,15 @@ void HostMemory::ClearBackingRegion(size_t physical_offset, size_t length, u32 f const size_t granule_end = granule_begin + (size_t{1} << GranuleShift); const size_t clear_end = (std::min)(granule_end, end); if ((granules[index].load(std::memory_order_acquire) & GranuleDirty) != 0) { - std::memset(backing_base + offset, 0, clear_end - offset); - if (offset == granule_begin && clear_end == granule_end) { + const bool whole = offset == granule_begin && clear_end == granule_end; + bool cleared = false; +#ifdef __linux__ + cleared = whole && punch && impl && impl->PunchHole(granule_begin, granule_end - granule_begin); +#endif + if (!cleared) { + std::memset(backing_base + offset, 0, clear_end - offset); + } + if (whole) { granules[index].fetch_and(static_cast<u8>(~GranuleDirty), std::memory_order_release); } } |
