Răsfoiți Sursa

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.
ReinUsesLisp 5 ani în urmă
părinte
comite
7402442442

+ 16 - 9
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<StagingBufferRef> 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<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) {
+        return *ref;
+    }
+    return CreateStagingBuffer(size, usage);
+}
+
 std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size,
                                                                         MemoryUsage usage) {
     StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)];

+ 2 - 0
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<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage);
 
     StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage);