diff options
Diffstat (limited to 'src/video_core/memory_manager.cpp')
| -rw-r--r-- | src/video_core/memory_manager.cpp | 34 |
1 files changed, 32 insertions, 2 deletions
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 0eae8fac24..2dd8b04656 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -120,11 +120,26 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr de page_table.ReserveRange(gpu_addr, size); } for (u64 offset{}; offset < size; offset += page_size) { + // The caches hear about each run of pages whose entry changed in one call, not page by page + // (a 1.45 GB Switch 2 region made ~370,000 texture cache scans). + GPUVAddr modified_start{}; + u64 modified_size{}; + const auto flush_modified = [&] { + if (modified_size != 0) { + rasterizer->ModifyGPUMemory(unique_identifier, modified_start, modified_size); + modified_size = 0; + } + }; const GPUVAddr current_gpu_addr = gpu_addr + offset; [[maybe_unused]] const auto current_entry_type = GetEntry(current_gpu_addr, false); SetEntry(current_gpu_addr, entry_type, false); if (current_entry_type != entry_type) { - rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, page_size); + if (modified_size == 0) { + modified_start = current_gpu_addr; + } + modified_size += page_size; + } else { + flush_modified(); } if (entry_type == EntryType::Mapped) { const DAddr current_dev_addr = dev_addr + offset; @@ -135,17 +150,31 @@ GPUVAddr MemoryManager::PageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr de remaining_size -= page_size; } kind_map.Map(gpu_addr, gpu_addr + size, kind); + flush_modified(); return gpu_addr; } GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr dev_addr, size_t size, PTEKind kind, MemoryManager::EntryType entry_type) { [[maybe_unused]] u64 remaining_size{size}; for (u64 offset{}; offset < size; offset += big_page_size) { + GPUVAddr modified_start{}; + u64 modified_size{}; + const auto flush_modified = [&] { + if (modified_size != 0) { + rasterizer->ModifyGPUMemory(unique_identifier, modified_start, modified_size); + modified_size = 0; + } + }; const GPUVAddr current_gpu_addr = gpu_addr + offset; [[maybe_unused]] const auto current_entry_type = GetEntry(current_gpu_addr, true); SetEntry(current_gpu_addr, entry_type, true); if (current_entry_type != entry_type) { - rasterizer->ModifyGPUMemory(unique_identifier, current_gpu_addr, big_page_size); + if (modified_size == 0) { + modified_start = current_gpu_addr; + } + modified_size += big_page_size; + } else { + flush_modified(); } if (entry_type == EntryType::Mapped) { const DAddr current_dev_addr = dev_addr + offset; @@ -173,6 +202,7 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] DAddr remaining_size -= big_page_size; } { + flush_modified(); std::unique_lock<std::mutex> lock(guard); kind_map.Map(gpu_addr, gpu_addr + size, kind); } |
