aboutsummaryrefslogtreecommitdiff
path: root/src/core
diff options
context:
space:
mode:
authorSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 13:18:13 -0500
committerSssnowyyy <78863999+Sssnowyyy@users.noreply.github.com>2026-11-02 14:53:47 -0500
commit9f4f01f76e8556941c0c0c3f57edc1d600ed23ea (patch)
tree8b0f38578d61852c3c27978baddd0c70daf84d9b /src/core
parentcd9b19c69d7eedc2d2d3557c27a0a06c4420213d (diff)
nx2: map GPU memory before later command lists are read
837133792d queues the GMMU maps on the GPU thread (GPU::RunInOrder) so the service thread never waits for the texture cache. With the GPU split (Low GPU accuracy) the GPU thread defers queued functions to its back, but its front reads the command lists: it read the lists submitted after a map through GPU addresses that weren't mapped yet. Pokopia stopped after its first frame. Add GPU::MapInOrder for the GMMU maps and the sparse tile remaps. It runs in order like RunInOrder, and with the split it runs on the front after draining the back, before the front reads further command lists. The service thread still never takes the texture cache lock, and the back is idle while the map changes the caches. Unmaps and the other queued work still run on the back. Assisted-by: Claude Opus 5.5 (bisect, fix, testing and commit message)
Diffstat (limited to 'src/core')
-rw-r--r--src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp6
1 files changed, 3 insertions, 3 deletions
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
index 843d31caf1..c5b23bef3e 100644
--- a/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_as_gpu.cpp
@@ -176,7 +176,7 @@ void nvhost_as_gpu::Nx2Map(u64 gpu_address, u64 cpu_address, u64 size) {
Nx2GpuMemoryRegistry::Get().RecordDeviceRange(cpu_address, size, device_address);
// On the GPU thread, like unmaps: a GMMU map takes the texture cache lock, and the callers hold
// nx2:gpu locks that the GPU thread takes under that lock (sparse blocks backed on write).
- system.GPU().RunInOrder([gmmu = gmmu.get(), gpu_address, device_address, size] {
+ system.GPU().MapInOrder([gmmu = gmmu.get(), gpu_address, device_address, size] {
gmmu->Map(gpu_address, device_address, size, Tegra::PTEKind::PITCH, false);
});
LOG_DEBUG(Service_NVDRV, "Switch 2 GPU mapping {:#x}+{:#x} -> CPU {:#x}", gpu_address, size,
@@ -253,7 +253,7 @@ void nvhost_as_gpu::Nx2Sparse(u64 gpu_address, u64 size, bool create) {
}
nx2_sparse_ranges[gpu_address] = {size, device_address};
// On the GPU thread, as in Nx2Map.
- system.GPU().RunInOrder([gmmu = gmmu.get(), gpu_address, device_address, size] {
+ system.GPU().MapInOrder([gmmu = gmmu.get(), gpu_address, device_address, size] {
gmmu->Map(gpu_address, device_address, size, Tegra::PTEKind::PITCH, false);
});
LOG_DEBUG(Service_NVDRV, "Switch 2 sparse region {:#x}+{:#x} -> device {:#x}", gpu_address,
@@ -295,7 +295,7 @@ void nvhost_as_gpu::Nx2SparseTile(u64 gpu_address, u64 cpu_address, u64 size) {
// whose contents are now what the game's memory holds there.
const DAddr device = device_address + (gpu_address - start);
auto& smmu = system.Host1x().MemoryManager();
- system.GPU().RunInOrder([&smmu, device, cpu_address, size, asid = session->asid] {
+ system.GPU().MapInOrder([&smmu, device, cpu_address, size, asid = session->asid] {
smmu.Unmap(device, size);
if (cpu_address != 0) {
smmu.Map(device, cpu_address, size, asid, true);