summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp62
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.h23
2 files changed, 85 insertions, 0 deletions
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.cpp b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
index 2e9c6ef34..39c33c8cc 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -4,12 +4,16 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include "common/assert.h" 6#include "common/assert.h"
7#include "common/logging/log.h"
7#include "video_core/renderer_vulkan/declarations.h" 8#include "video_core/renderer_vulkan/declarations.h"
8#include "video_core/renderer_vulkan/vk_device.h" 9#include "video_core/renderer_vulkan/vk_device.h"
9#include "video_core/renderer_vulkan/vk_resource_manager.h" 10#include "video_core/renderer_vulkan/vk_resource_manager.h"
10 11
11namespace Vulkan { 12namespace Vulkan {
12 13
14// TODO(Rodrigo): Fine tune these numbers.
15constexpr std::size_t FENCES_GROW_STEP = 0x40;
16
13VKResource::VKResource() = default; 17VKResource::VKResource() = default;
14 18
15VKResource::~VKResource() = default; 19VKResource::~VKResource() = default;
@@ -117,4 +121,62 @@ void VKFenceWatch::OnFenceRemoval(VKFence* signaling_fence) {
117 fence = nullptr; 121 fence = nullptr;
118} 122}
119 123
124VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
125 GrowFences(FENCES_GROW_STEP);
126}
127
128VKResourceManager::~VKResourceManager() = default;
129
130VKFence& VKResourceManager::CommitFence() {
131 const auto StepFences = [&](bool gpu_wait, bool owner_wait) -> VKFence* {
132 const auto Tick = [=](auto& fence) { return fence->Tick(gpu_wait, owner_wait); };
133 const auto hinted = fences.begin() + fences_iterator;
134
135 auto it = std::find_if(hinted, fences.end(), Tick);
136 if (it == fences.end()) {
137 it = std::find_if(fences.begin(), hinted, Tick);
138 if (it == hinted) {
139 return nullptr;
140 }
141 }
142 fences_iterator = std::distance(fences.begin(), it) + 1;
143 if (fences_iterator >= fences.size())
144 fences_iterator = 0;
145
146 auto& fence = *it;
147 fence->Commit();
148 return fence.get();
149 };
150
151 VKFence* found_fence = StepFences(false, false);
152 if (!found_fence) {
153 // Try again, this time waiting.
154 found_fence = StepFences(true, false);
155
156 if (!found_fence) {
157 // Allocate new fences and try again.
158 LOG_INFO(Render_Vulkan, "Allocating new fences {} -> {}", fences.size(),
159 fences.size() + FENCES_GROW_STEP);
160
161 GrowFences(FENCES_GROW_STEP);
162 found_fence = StepFences(true, false);
163 ASSERT(found_fence != nullptr);
164 }
165 }
166 return *found_fence;
167}
168
169void VKResourceManager::GrowFences(std::size_t new_fences_count) {
170 const auto dev = device.GetLogical();
171 const auto& dld = device.GetDispatchLoader();
172 const vk::FenceCreateInfo fence_ci;
173
174 const std::size_t previous_size = fences.size();
175 fences.resize(previous_size + new_fences_count);
176
177 std::generate(fences.begin() + previous_size, fences.end(), [&]() {
178 return std::make_unique<VKFence>(device, dev.createFenceUnique(fence_ci, nullptr, dld));
179 });
180}
181
120} // namespace Vulkan 182} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.h b/src/video_core/renderer_vulkan/vk_resource_manager.h
index 5345ba46e..c8759f779 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.h
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.h
@@ -4,6 +4,8 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <cstddef>
8#include <memory>
7#include <vector> 9#include <vector>
8#include "video_core/renderer_vulkan/declarations.h" 10#include "video_core/renderer_vulkan/declarations.h"
9 11
@@ -116,4 +118,25 @@ private:
116 VKFence* fence{}; ///< Fence watching this resource. nullptr when the watch is free. 118 VKFence* fence{}; ///< Fence watching this resource. nullptr when the watch is free.
117}; 119};
118 120
121/**
122 * The resource manager handles all resources that can be protected with a fence avoiding
123 * driver-side or GPU-side concurrent usage. Usage is documented in VKFence.
124 */
125class VKResourceManager final {
126public:
127 explicit VKResourceManager(const VKDevice& device);
128 ~VKResourceManager();
129
130 /// Commits a fence. It has to be sent to a queue and released.
131 VKFence& CommitFence();
132
133private:
134 /// Allocates new fences.
135 void GrowFences(std::size_t new_fences_count);
136
137 const VKDevice& device; ///< Device handler.
138 std::size_t fences_iterator = 0; ///< Index where a free fence is likely to be found.
139 std::vector<std::unique_ptr<VKFence>> fences; ///< Pool of fences.
140};
141
119} // namespace Vulkan 142} // namespace Vulkan