diff options
| author | Mako <137927095+Takoroka@users.noreply.github.com> | 2026-10-30 21:10:10 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-10-30 21:10:10 -0400 |
| commit | b40ad217ab829226841cb71f6e4c5cb05977a225 (patch) | |
| tree | f6401dcd82c03ce1e1b03ab728818f149a0e9277 /src | |
| parent | 783ddef23ecb7ed51ef6466ad401745f85acbb7f (diff) | |
| parent | ddd367a8152f1c37bfc972475b40afece2da31ac (diff) | |
Merge pull request #48 from Djihads80/fix/device-memory-page-runs
core: end device page runs where pages are unmapped or mapped again
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/device_memory_manager.h | 2 | ||||
| -rw-r--r-- | src/core/device_memory_manager.inc | 21 |
2 files changed, 23 insertions, 0 deletions
diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index 46cda14e78..9c034f01a1 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h @@ -187,6 +187,8 @@ private: void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory, auto increment); + void CutContinuityAt(size_t page); + void InnerGatherDeviceAddresses(Common::ScratchBuffer<u32>& buffer, PAddr address); std::unique_ptr<DeviceMemoryManagerAllocator<Traits>> impl; diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index d78a229e1f..c45bc71656 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc @@ -211,9 +211,13 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size std::scoped_lock lk(mapping_guard); tracked_entries.CommitRegion(start_page_d, start_page_d + num_pages); + CutContinuityAt(start_page_d); for (size_t i = 0; i < num_pages; i++) { const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE; auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)); + // One page per run unless tracked below: a run left from an earlier mapping of these + // device pages would make WalkBlock copy the host memory that followed that mapping. + tracked_entries.GetUnchecked(start_page_d + i).continuity_tracker = 0; if (ptr == nullptr) [[unlikely]] { tracked_entries.GetUnchecked(start_page_d + i).compressed_physical_ptr = 0; continue; @@ -248,11 +252,13 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { std::scoped_lock lk(mapping_guard); tracked_entries.CommitRegion(start_page_d, start_page_d + num_pages); // should already be committed, but just in case + CutContinuityAt(start_page_d); for (size_t i = 0; i < num_pages; i++) { auto& entry = tracked_entries.GetUnchecked(start_page_d + i); auto phys_addr = entry.compressed_physical_ptr; entry.compressed_physical_ptr = 0; entry.cpu_backing_address = 0; + entry.continuity_tracker = 0; if (phys_addr != 0) [[likely]] { u32& base_dev = compressed_device_addr.GetAndFault(phys_addr - 1U); if ((base_dev >> MULTI_FLAG_BITS) == 0) [[likely]] { @@ -270,6 +276,21 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { } translation_generation.fetch_add(1, std::memory_order_release); } + +template <typename Traits> +void DeviceMemoryManager<Traits>::CutContinuityAt(size_t page) { + // Runs counted from the pages before `page` end there: the pages from `page` on are being + // mapped again or unmapped. A run is counted down page by page (TrackContinuityImpl), so the + // first page whose run already ends before `page` ends the walk. + for (size_t index = page; index-- > 0;) { + const size_t last_count = page - 1 - index; + if (tracked_entries[index].continuity_tracker <= last_count) { + break; + } + tracked_entries.GetUnchecked(index).continuity_tracker = static_cast<u32>(last_count); + } +} + template <typename Traits> void DeviceMemoryManager<Traits>::TrackContinuityImpl(DAddr address, VAddr virtual_address, size_t size, Asid asid) { |
