From 8a244677d718727c598c58a5875d73034aca49f7 Mon Sep 17 00:00:00 2001 From: nmzik Date: Wed, 29 Jul 2026 17:13:19 +0200 Subject: [PATCH] fix(renderer): resolve delayed GPU page faults through buffer and texture caches --- src/graphics/host_gpu/renderer/cache/bufferCache.cpp | 3 ++- src/graphics/host_gpu/renderer/cache/bufferCache.h | 2 +- .../host_gpu/renderer/cache/gpuResourceManager.cpp | 12 +++++++++--- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp index 0f356a12e..3e5bf9a3b 100644 --- a/src/graphics/host_gpu/renderer/cache/bufferCache.cpp +++ b/src/graphics/host_gpu/renderer/cache/bufferCache.cpp @@ -394,6 +394,7 @@ void BufferCache::InvalidateMemory(uint64_t vaddr, uint64_t size) { } void BufferCache::ReadMemory(uint64_t vaddr, uint64_t size) { + (void)SynchronizeBacking(vaddr, size); std::vector copies; { FaultSafeCacheLock lock(this, m_mutex); @@ -426,7 +427,7 @@ void BufferCache::ReadMemory(uint64_t vaddr, uint64_t size) { }); } if (copies.empty()) { - EXIT("BufferCache: GPU-owned invalidation has no dirty byte ranges\n"); + return; } auto downloads = RecordDownloads(copies); m_scheduler.FinishCurrent(); diff --git a/src/graphics/host_gpu/renderer/cache/bufferCache.h b/src/graphics/host_gpu/renderer/cache/bufferCache.h index d390f5072..9ce431083 100644 --- a/src/graphics/host_gpu/renderer/cache/bufferCache.h +++ b/src/graphics/host_gpu/renderer/cache/bufferCache.h @@ -50,6 +50,7 @@ public: [[nodiscard]] bool InvalidateMemory(PageFaultAccess access, uint64_t vaddr, uint64_t size, PageFaultPhase phase) noexcept; void InvalidateMemory(uint64_t vaddr, uint64_t size); + void ReadMemory(uint64_t vaddr, uint64_t size); void UnmapMemory(uint64_t vaddr, uint64_t size); [[nodiscard]] BufferBinding ObtainBuffer(CommandBuffer& command, uint64_t vaddr, uint64_t size, bool is_written = false, bool is_read = true, @@ -111,7 +112,6 @@ private: void QueueGarbageDownload(std::span copies, RetiredBuffer retire); void RefreshInvalidatedRanges(CommandBuffer& command, CachedBuffer& cached, uint64_t vaddr, uint64_t size, bool upload); - void ReadMemory(uint64_t vaddr, uint64_t size); void DiscardGpuDirtyBytesLocked(uint64_t vaddr, uint64_t size, const char* operation); void WriteHostMemory(uint64_t vaddr, std::span data); diff --git a/src/graphics/host_gpu/renderer/cache/gpuResourceManager.cpp b/src/graphics/host_gpu/renderer/cache/gpuResourceManager.cpp index 7ff188a19..1f7f6693f 100644 --- a/src/graphics/host_gpu/renderer/cache/gpuResourceManager.cpp +++ b/src/graphics/host_gpu/renderer/cache/gpuResourceManager.cpp @@ -36,7 +36,8 @@ bool GpuResourceManager::InvalidateMemory(PageFaultAccess access, uint64_t vaddr } bool GpuResourceManager::HandleFault(PageFaultAccess access, uint64_t fault_vaddr) noexcept { - if (!m_page_manager.IsMapped(fault_vaddr, 1)) { + constexpr uint64_t fault_size = 8; + if (!IsMapped(fault_vaddr, fault_size)) { return false; } if (CommandScheduler::InDeferredOperation()) { @@ -47,10 +48,15 @@ bool GpuResourceManager::HandleFault(PageFaultAccess access, uint64_t fault_vadd bool handled = false; const auto resolve = [this, access, fault_vaddr, &handled](CommandProcessor& cp) { cp.BeginReadbackTransaction(); - (void)m_buffer_cache.SynchronizeBacking(fault_vaddr, 1); { ResourceMutex::FaultScope fault(m_resource_mutex); - handled = m_page_manager.HandleFault(access, fault_vaddr); + if (access == PageFaultAccess::Write) { + m_buffer_cache.InvalidateMemory(fault_vaddr, fault_size); + m_texture_cache.InvalidateMemory(fault_vaddr, fault_size); + } else { + m_buffer_cache.ReadMemory(fault_vaddr, fault_size); + } + handled = true; } cp.EndReadbackTransaction(); };