summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_staging_buffer_pool.h26
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
143StagingBufferPool::~StagingBufferPool() = default; 143StagingBufferPool::~StagingBufferPool() = default;
144 144
145StagingBufferRef StagingBufferPool::Request(size_t size, MemoryUsage usage) { 145StagingBufferRef 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
152void 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
152void StagingBufferPool::TickFrame() { 164void 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
199StagingBufferRef StagingBufferPool::GetStagingBuffer(size_t size, MemoryUsage usage) { 211StagingBufferRef 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
206std::optional<StagingBufferRef> StagingBufferPool::TryGetReservedBuffer(size_t size, 219std::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
227StagingBufferRef StagingBufferPool::CreateStagingBuffer(size_t size, MemoryUsage usage) { 243StagingBufferRef 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
25class StagingBufferPool { 29class 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