diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 07:09:36 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-29 20:49:47 -0400 |
| commit | 1c7c24683fd51c6135137c4ff2ee2d742c5fff36 (patch) | |
| tree | 4e9bfc81e258a43c89a8761883a86741fe58394f /src | |
| parent | 6912d650f7d0b47dfec9705ca6c400f90ada5bef (diff) | |
vulkan: defer the caches' invalidation for inline writes outside GPU-written data
Title 1 makes thousands of small inline-to-memory writes between draws, and each one
invalidated the buffer, texture, shader and query caches on its own (~7.5% of the GPU
thread after 0fe581f). Guest memory is still written at once, query results pending
there are still dropped at once, and writes into GPU-written buffer data are still
uploaded in place; the buffer, texture and shader caches now get the merged ranges at
the next FlushCaching, which runs before every draw, dispatch, clear, copy and 2D blit.
Inline writes: 4.4% of the GPU thread (deferred invalidation included in FlushCaching,
3.9% -> 3.1%). EDEN_NX2_INLINE_DEFER=0 invalidates at once.
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/memory_manager.h | 6 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_rasterizer.cpp | 21 |
2 files changed, 25 insertions, 2 deletions
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index 105cb14e23..bd5025e9fd 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h @@ -165,6 +165,12 @@ public: void FlushCaching(); + /// Leaves the caches' invalidation of a range already written for the next FlushCaching + /// (before every draw, dispatch, clear and copy), merged with neighbouring ranges. + void AccumulateInvalidation(GPUVAddr gpu_addr, std::size_t size) { + accumulator.Add(gpu_addr, size); + } + const u8* GetSpan(const GPUVAddr src_addr, const std::size_t size) const; u8* GetSpan(const GPUVAddr src_addr, const std::size_t size); diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index b5837e6a55..0826820714 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp @@ -1250,20 +1250,37 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si return; } gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size); + // EDEN_NX2_INLINE_DEFER=0: invalidate every cache at once (for comparisons). + static const bool defer = [] { + const char* value = std::getenv("EDEN_NX2_INLINE_DEFER"); + return value == nullptr || value[0] != '0'; + }(); // One cache at a time: holding both while waiting for either (std::lock) waited longer, the // fencing thread and CPU write traps holding one of them most of the time. + bool uploaded; { std::scoped_lock lock{buffer_cache.mutex}; - if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) { + uploaded = buffer_cache.InlineMemory(*cpu_addr, copy_size, memory); + if (!uploaded && !defer) { buffer_cache.WriteMemory(*cpu_addr, copy_size); } } + // Pending query results must not land over the new words later: drop them now. + query_cache.InvalidateRegion(*cpu_addr, copy_size); + if (!uploaded && defer) { + // Title 1 makes thousands of small inline writes between draws (~10% of the GPU + // thread invalidating every cache for each). Guest memory is written; the buffer, + // texture and shader caches see the merged ranges at the next FlushCaching, which runs + // before anything of theirs is used. Writes into GPU-written buffer data were uploaded + // in place above, as before. + gpu_memory->AccumulateInvalidation(address, copy_size); + return; + } { std::scoped_lock lock{texture_cache.mutex}; texture_cache.WriteMemory(*cpu_addr, copy_size); } pipeline_cache.InvalidateRegion(*cpu_addr, copy_size); - query_cache.InvalidateRegion(*cpu_addr, copy_size); } std::optional<FramebufferTextureInfo> RasterizerVulkan::AccelerateDisplay( |
