aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
authorkraibse <33869366+kraibse@users.noreply.github.com>2026-11-02 13:50:54 +0100
committerkraibse <33869366+kraibse@users.noreply.github.com>2026-11-02 14:43:01 +0100
commitc0cb3325e22756edb65c87d33ef298349ade0ad3 (patch)
treee3f6d670018b57004915e69d1fc741b4efecb325 /src/common
parent9210b8d69d172b5456e90cbd56b8f2bacbd7386b (diff)
parenta407703f6d29a5ab73328b4ededb12cf29b2758d (diff)
Merge nx2 into nx2-experimental
Resolved by area: - audio feature_support.h: nx2's native revision handling. - fiber.cpp: ours, which also drops the unused rewind stack. - host_memory.cpp: ours granule bitmap and HintCold, plus nx2's fallocate hole punching per whole dirty granule on Linux. - texture_cache.h: nx2's old-age eviction pass, then our Collect(). - kepler_compute.cpp: shared upscale slots, then Fortune's Weave's, then the Kirby Air Riders scan. - nx2_gsv.h: ours, plus nx2's GetBufferMaxResolution and graphics device ids (1-based). - nvhost_ctrl_gpu.cpp: engine support flag bits 40-44. - lower_to_maxwell.h: ours as the base, with nx2's seven lowering commits applied one at a time. Second texture descriptor buffers are read bindless in TEX, TLD.SCR (level zero) and SUST; FSEL keeps its operand modifiers; TXD takes any channel mask. lower_to_maxwell.h lowers 837 Fortune's Weave and 1183 Mario Kart World shader dumps with the same rejects as nx2 and ours (12 and 0). Assisted-by: Claude Sonnet 5.5 (conflict analysis and drafting)
Diffstat (limited to 'src/common')
-rw-r--r--src/common/host_memory.cpp27
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);
}
}