aboutsummaryrefslogtreecommitdiff
path: root/src/video_core/renderer_vulkan
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 01:51:42 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 01:51:42 -0400
commite08b40252790eef96337409d7dd606aa7bfa8428 (patch)
treed94274e2c27fa43a99200258558437807a785bd4 /src/video_core/renderer_vulkan
parentae980ab79568c80ed5760f7fd5f452c8a49dc1ab (diff)
video_core: less waiting on the GPU caches' locks
- The texture and buffer caches' mutexes spin briefly before sleeping (Common::SpinRecursiveMutex): the GPU thread, the fencing thread and CPU write traps take them tens of thousands of times a second for microseconds, and a sleeping waiter's wake-up took longer than that. Title 1's GPU thread slept 7.7% of its time there, now 3.7%. - Fences commit and pop texture and buffer downloads separately, and only when there are any (one fence per compute dispatch in Switch 2 titles): the fencing thread no longer holds both caches while it copies buffer downloads. - Inline uploads and pre-draw invalidation take the caches one at a time again: holding one while std::lock waited for the other waited longer.
Diffstat (limited to 'src/video_core/renderer_vulkan')
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp14
1 files changed, 10 insertions, 4 deletions
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 886c5dbfe4..429b2d63ef 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -1036,11 +1036,13 @@ void RasterizerVulkan::InvalidateRegion(DAddr addr, u64 size, VideoCommon::Cache
void RasterizerVulkan::InnerInvalidation(std::span<const std::pair<DAddr, std::size_t>> sequences) {
{
- // Both caches under one lock: this runs before most draws (constant buffer updates).
- std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
+ std::scoped_lock lock{texture_cache.mutex};
for (const auto& [addr, size] : sequences) {
texture_cache.WriteMemory(addr, size);
}
+ }
+ {
+ std::scoped_lock lock{buffer_cache.mutex};
for (const auto& [addr, size] : sequences) {
buffer_cache.WriteMemory(addr, size);
}
@@ -1248,12 +1250,16 @@ void RasterizerVulkan::AccelerateInlineToMemory(GPUVAddr address, size_t copy_si
return;
}
gpu_memory->WriteBlockUnsafe(address, memory.data(), copy_size);
+ // 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.
{
- // Both caches under one lock (title 1 makes thousands of inline uploads a second).
- std::scoped_lock lock{buffer_cache.mutex, texture_cache.mutex};
+ std::scoped_lock lock{buffer_cache.mutex};
if (!buffer_cache.InlineMemory(*cpu_addr, copy_size, memory)) {
buffer_cache.WriteMemory(*cpu_addr, copy_size);
}
+ }
+ {
+ std::scoped_lock lock{texture_cache.mutex};
texture_cache.WriteMemory(*cpu_addr, copy_size);
}
pipeline_cache.InvalidateRegion(*cpu_addr, copy_size);