diff options
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | 51 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_staging_buffer_pool.h | 26 |
2 files changed, 56 insertions, 21 deletions
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 06f68d09a..202806331 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 3 | 3 | ||
| 4 | #include <algorithm> | 4 | #include <algorithm> |
| 5 | #include <utility> | 5 | #include <utility> |
| @@ -94,7 +94,7 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem | |||
| 94 | .flags = 0, | 94 | .flags = 0, |
| 95 | .size = STREAM_BUFFER_SIZE, | 95 | .size = STREAM_BUFFER_SIZE, |
| 96 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | | 96 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | |
| 97 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT, | 97 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT , |
| 98 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 98 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 99 | .queueFamilyIndexCount = 0, | 99 | .queueFamilyIndexCount = 0, |
| 100 | .pQueueFamilyIndices = nullptr, | 100 | .pQueueFamilyIndices = nullptr, |
| @@ -142,11 +142,23 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem | |||
| 142 | 142 | ||
| 143 | StagingBufferPool::~StagingBufferPool() = default; | 143 | StagingBufferPool::~StagingBufferPool() = default; |
| 144 | 144 | ||
| 145 | StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) { | 145 | StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage, bool deferred) { |
| 146 | if (usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { | 146 | if (!deferred && usage == MemoryUsage::Upload && size <= MAX_STREAM_BUFFER_REQUEST_SIZE) { |
| 147 | return GetStreamBuffer(size); | 147 | return GetStreamBuffer(size); |
| 148 | } | 148 | } |
| 149 | return GetStagingBuffer(size, usage); | 149 | return GetStagingBuffer(size, usage, deferred); |
| 150 | } | ||
| 151 | |||
| 152 | void StagingBufferPool::FreeDeferred(StagingBufferRef& ref) { | ||
| 153 | auto& entries = GetCache(ref.usage)[ref.log2_level].entries; | ||
| 154 | const auto is_this_one = [&ref](const StagingBuffer& entry) { | ||
| 155 | return entry.index == ref.index; | ||
| 156 | }; | ||
| 157 | auto it = std::find_if(entries.begin(), entries.end(), is_this_one); | ||
| 158 | ASSERT(it != entries.end()); | ||
| 159 | ASSERT(it->deferred); | ||
| 160 | it->tick = scheduler.CurrentTick(); | ||
| 161 | it->deferred = false; | ||
| 150 | } | 162 | } |
| 151 | 163 | ||
| 152 | void StagingBufferPool::TickFrame() { | 164 | void StagingBufferPool::TickFrame() { |
| @@ -196,19 +208,21 @@ bool StagingBufferPool::AreRegionsActive(size_t region_begin, size_t region_end) | |||
| 196 | [gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; }); | 208 | [gpu_tick](u64 sync_tick) { return gpu_tick < sync_tick; }); |
| 197 | }; | 209 | }; |
| 198 | 210 | ||
| 199 | StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage) { | 211 | StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage, |
| 200 | if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage)) { | 212 | bool deferred) { |
| 213 | if (const std::optional<StagingBufferRef> ref = TryGetReservedBuffer(size, usage, deferred)) { | ||
| 201 | return *ref; | 214 | return *ref; |
| 202 | } | 215 | } |
| 203 | return CreateStagingBuffer(size, usage); | 216 | return CreateStagingBuffer(size, usage, deferred); |
| 204 | } | 217 | } |
| 205 | 218 | ||
| 206 | std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, | 219 | std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, |
| 207 | MemoryUsage usage) { | 220 | MemoryUsage usage, |
| 221 | bool deferred) { | ||
| 208 | StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)]; | 222 | StagingBuffers& cache_level = GetCache(usage)[Common::Log2Ceil64(size)]; |
| 209 | 223 | ||
| 210 | const auto is_free = [this](const StagingBuffer& entry) { | 224 | const auto is_free = [this](const StagingBuffer& entry) { |
| 211 | return scheduler.IsFree(entry.tick); | 225 | return !entry.deferred && scheduler.IsFree(entry.tick); |
| 212 | }; | 226 | }; |
| 213 | auto& entries = cache_level.entries; | 227 | auto& entries = cache_level.entries; |
| 214 | const auto hint_it = entries.begin() + cache_level.iterate_index; | 228 | const auto hint_it = entries.begin() + cache_level.iterate_index; |
| @@ -220,11 +234,14 @@ std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t s | |||
| 220 | } | 234 | } |
| 221 | } | 235 | } |
| 222 | cache_level.iterate_index = std::distance(entries.begin(), it) + 1; | 236 | cache_level.iterate_index = std::distance(entries.begin(), it) + 1; |
| 223 | it->tick = scheduler.CurrentTick(); | 237 | it->tick = deferred ? std::numeric_limits<u64>::max() : scheduler.CurrentTick(); |
| 238 | ASSERT(!it->deferred); | ||
| 239 | it->deferred = deferred; | ||
| 224 | return it->Ref(); | 240 | return it->Ref(); |
| 225 | } | 241 | } |
| 226 | 242 | ||
| 227 | StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage) { | 243 | StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage, |
| 244 | bool deferred) { | ||
| 228 | const u32 log2 = Common::Log2Ceil64(size); | 245 | const u32 log2 = Common::Log2Ceil64(size); |
| 229 | vk::Buffer buffer = device.GetLogical().CreateBuffer({ | 246 | vk::Buffer buffer = device.GetLogical().CreateBuffer({ |
| 230 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 247 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| @@ -233,7 +250,7 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage | |||
| 233 | .size = 1ULL << log2, | 250 | .size = 1ULL << log2, |
| 234 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | | 251 | .usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT | |
| 235 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | | 252 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | |
| 236 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, | 253 | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT , |
| 237 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 254 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 238 | .queueFamilyIndexCount = 0, | 255 | .queueFamilyIndexCount = 0, |
| 239 | .pQueueFamilyIndices = nullptr, | 256 | .pQueueFamilyIndices = nullptr, |
| @@ -249,7 +266,11 @@ StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage | |||
| 249 | .buffer = std::move(buffer), | 266 | .buffer = std::move(buffer), |
| 250 | .commit = std::move(commit), | 267 | .commit = std::move(commit), |
| 251 | .mapped_span = mapped_span, | 268 | .mapped_span = mapped_span, |
| 252 | .tick = scheduler.CurrentTick(), | 269 | .usage = usage, |
| 270 | .log2_level = log2, | ||
| 271 | .index = unique_ids++, | ||
| 272 | .tick = deferred ? std::numeric_limits<u64>::max() : scheduler.CurrentTick(), | ||
| 273 | .deferred = deferred, | ||
| 253 | }); | 274 | }); |
| 254 | return entry.Ref(); | 275 | return entry.Ref(); |
| 255 | } | 276 | } |
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 91dc84da8..2906d92a4 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.h | |||
| @@ -1,5 +1,6 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project | 1 | // Copyright 2019 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | ||
| 3 | 4 | ||
| 4 | #pragma once | 5 | #pragma once |
| 5 | 6 | ||
| @@ -20,6 +21,9 @@ struct StagingBufferRef { | |||
| 20 | VkBuffer buffer; | 21 | VkBuffer buffer; |
| 21 | VkDeviceSize offset; | 22 | VkDeviceSize offset; |
| 22 | std::span<u8> mapped_span; | 23 | std::span<u8> mapped_span; |
| 24 | MemoryUsage usage; | ||
| 25 | u32 log2_level; | ||
| 26 | u64 index; | ||
| 23 | }; | 27 | }; |
| 24 | 28 | ||
| 25 | class StagingBufferPool { | 29 | class StagingBufferPool { |
| @@ -30,7 +34,8 @@ public: | |||
| 30 | Scheduler& scheduler); | 34 | Scheduler& scheduler); |
| 31 | ~StagingBufferPool(); | 35 | ~StagingBufferPool(); |
| 32 | 36 | ||
| 33 | StagingBufferRef Request(size_t size, MemoryUsage usage); | 37 | StagingBufferRef Request(size_t size, MemoryUsage usage, bool deferred = false); |
| 38 | void FreeDeferred(StagingBufferRef& ref); | ||
| 34 | 39 | ||
| 35 | void TickFrame(); | 40 | void TickFrame(); |
| 36 | 41 | ||
| @@ -44,13 +49,20 @@ private: | |||
| 44 | vk::Buffer buffer; | 49 | vk::Buffer buffer; |
| 45 | MemoryCommit commit; | 50 | MemoryCommit commit; |
| 46 | std::span<u8> mapped_span; | 51 | std::span<u8> mapped_span; |
| 52 | MemoryUsage usage; | ||
| 53 | u32 log2_level; | ||
| 54 | u64 index; | ||
| 47 | u64 tick = 0; | 55 | u64 tick = 0; |
| 56 | bool deferred{}; | ||
| 48 | 57 | ||
| 49 | StagingBufferRef Ref() const noexcept { | 58 | StagingBufferRef Ref() const noexcept { |
| 50 | return { | 59 | return { |
| 51 | .buffer = *buffer, | 60 | .buffer = *buffer, |
| 52 | .offset = 0, | 61 | .offset = 0, |
| 53 | .mapped_span = mapped_span, | 62 | .mapped_span = mapped_span, |
| 63 | .usage = usage, | ||
| 64 | .log2_level = log2_level, | ||
| 65 | .index = index, | ||
| 54 | }; | 66 | }; |
| 55 | } | 67 | } |
| 56 | }; | 68 | }; |
| @@ -68,11 +80,12 @@ private: | |||
| 68 | 80 | ||
| 69 | bool AreRegionsActive(size_t region_begin, size_t region_end) const; | 81 | bool AreRegionsActive(size_t region_begin, size_t region_end) const; |
| 70 | 82 | ||
| 71 | StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage); | 83 | StagingBufferRef GetStagingBuffer(size_t size, MemoryUsage usage, bool deferred = false); |
| 72 | 84 | ||
| 73 | std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage); | 85 | std::optional<StagingBufferRef> TryGetReservedBuffer(size_t size, MemoryUsage usage, |
| 86 | bool deferred); | ||
| 74 | 87 | ||
| 75 | StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage); | 88 | StagingBufferRef CreateStagingBuffer(size_t size, MemoryUsage usage, bool deferred); |
| 76 | 89 | ||
| 77 | StagingBuffersCache& GetCache(MemoryUsage usage); | 90 | StagingBuffersCache& GetCache(MemoryUsage usage); |
| 78 | 91 | ||
| @@ -99,6 +112,7 @@ private: | |||
| 99 | 112 | ||
| 100 | size_t current_delete_level = 0; | 113 | size_t current_delete_level = 0; |
| 101 | u64 buffer_index = 0; | 114 | u64 buffer_index = 0; |
| 115 | u64 unique_ids{}; | ||
| 102 | }; | 116 | }; |
| 103 | 117 | ||
| 104 | } // namespace Vulkan | 118 | } // namespace Vulkan |