aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan/vk_rasterizer.cpp
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 07:09:36 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 20:49:47 -0400
commit1c7c24683fd51c6135137c4ff2ee2d742c5fff36 (patch)
tree4e9bfc81e258a43c89a8761883a86741fe58394f /src/video_core/renderer_vulkan/vk_rasterizer.cpp
parent6912d650f7d0b47dfec9705ca6c400f90ada5bef (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/video_core/renderer_vulkan/vk_rasterizer.cpp')
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp21
1 files changed, 19 insertions, 2 deletions
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(