aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/memory_manager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_core/memory_manager.cpp')
-rw-r--r--src/video_core/memory_manager.cpp34
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);
}