From 74024424422c81c77fc4f675da674503f6474589 Mon Sep 17 00:00:00 2001 From: ReinUsesLisp Date: Thu, 21 Jan 2021 01:07:11 -0300 Subject: vk_staging_buffer_pool: Get a staging buffer instead of waiting Avoids waiting idle while the GPU finishes to do work, and fixes an issue where we'd wait forever if a single command buffer (logic tick) all the data. --- .../renderer_vulkan/vk_staging_buffer_pool.cpp | 25 ++++++++++++++-------- .../renderer_vulkan/vk_staging_buffer_pool.h | 2 ++ 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'src/video_core/renderer_vulkan') diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index bc71202e2..4baf791d4 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp @@ -130,10 +130,7 @@ StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) { if (usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { return GetStreamBuffer(size); } - if (const std::optional ref = TryGetReservedBuffer(size, usage)) { - return *ref; - } - return CreateStagingBuffer(size, usage); + return GetStagingBuffer(size, usage); } void StagingBufferPool::TickFrame() { @@ -145,17 +142,20 @@ void StagingBufferPool::TickFrame() { } StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { + for (size_t region = Region(free_iterator) + 1, + region_end = std::min(Region(iterator + size) + 1, NUM_SYNCS); + region < region_end; ++region) { + // If we'd have to wait, get a staging buffer to avoid waiting + if (!scheduler.IsFree(sync_ticks[region])) { + return GetStagingBuffer(size, MemoryUsage::Upload); + } + } for (size_t region = Region(used_iterator), region_end = Region(iterator); region < region_end; ++region) { sync_ticks[region] = scheduler.CurrentTick(); } used_iterator = iterator; - for (size_t region = Region(free_iterator) + 1, - region_end = std::min(Region(iterator + size) + 1, NUM_SYNCS); - region < region_end; ++region) { - scheduler.Wait(sync_ticks[region]); - } if (iterator + size > free_iterator) { free_iterator = iterator + size; } @@ -180,6 +180,13 @@ StagingBufferRef StagingBufferPool::GetStreamBuffer(size_t size) { }; } +StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage) { + if (const std::optional ref = TryGetReservedBuffer(size, usage)) { + return *ref; + } + return CreateStagingBuffer(size, usage); +} + std::optional StagingBufferPool::TryGetReservedBuffer(size_t size, MemoryUsage usage) { StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)]; diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h index 4ed99c0df..8e4cadf9b 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h @@ -67,6 +67,8 @@ private: StagingBufferRef GetStreamBuffer(size_t size); + StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage); + std::optional TryGetReservedBuffer(size_t size, MemoryUsage usage); StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage); -- cgit v1.2.3