summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp51
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.h32
2 files changed, 83 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 39c33c8cc..e98ddba58 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.cpp
@@ -3,6 +3,7 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <algorithm> 5#include <algorithm>
6#include <optional>
6#include "common/assert.h" 7#include "common/assert.h"
7#include "common/logging/log.h" 8#include "common/logging/log.h"
8#include "video_core/renderer_vulkan/declarations.h" 9#include "video_core/renderer_vulkan/declarations.h"
@@ -121,6 +122,56 @@ void VKFenceWatch::OnFenceRemoval(VKFence* signaling_fence) {
121 fence = nullptr; 122 fence = nullptr;
122} 123}
123 124
125VKFencedPool::VKFencedPool(std::size_t grow_step) : grow_step{grow_step} {}
126
127VKFencedPool::~VKFencedPool() = default;
128
129std::size_t VKFencedPool::CommitResource(VKFence& fence) {
130 const auto Search = [&](std::size_t begin, std::size_t end) -> std::optional<std::size_t> {
131 for (std::size_t iterator = begin; iterator < end; ++iterator) {
132 if (watches[iterator]->TryWatch(fence)) {
133 // The resource is now being watched, a free resource was successfully found.
134 return iterator;
135 }
136 }
137 return {};
138 };
139 // Try to find a free resource from the hinted position to the end.
140 auto found = Search(free_iterator, watches.size());
141 if (!found) {
142 // Search from beginning to the hinted position.
143 found = Search(0, free_iterator);
144 if (!found) {
145 // Both searches failed, the pool is full; handle it.
146 const std::size_t free_resource = ManageOverflow();
147
148 // Watch will wait for the resource to be free.
149 watches[free_resource]->Watch(fence);
150 found = free_resource;
151 }
152 }
153 // Free iterator is hinted to the resource after the one that's been commited.
154 free_iterator = (*found + 1) % watches.size();
155 return *found;
156}
157
158std::size_t VKFencedPool::ManageOverflow() {
159 const std::size_t old_capacity = watches.size();
160 Grow();
161
162 // The last entry is guaranted to be free, since it's the first element of the freshly
163 // allocated resources.
164 return old_capacity;
165}
166
167void VKFencedPool::Grow() {
168 const std::size_t old_capacity = watches.size();
169 watches.resize(old_capacity + grow_step);
170 std::generate(watches.begin() + old_capacity, watches.end(),
171 []() { return std::make_unique<VKFenceWatch>(); });
172 Allocate(old_capacity, old_capacity + grow_step);
173}
174
124VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} { 175VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
125 GrowFences(FENCES_GROW_STEP); 176 GrowFences(FENCES_GROW_STEP);
126} 177}
diff --git a/src/video_core/renderer_vulkan/vk_resource_manager.h b/src/video_core/renderer_vulkan/vk_resource_manager.h
index c8759f779..1fd68bb4c 100644
--- a/src/video_core/renderer_vulkan/vk_resource_manager.h
+++ b/src/video_core/renderer_vulkan/vk_resource_manager.h
@@ -119,6 +119,38 @@ private:
119}; 119};
120 120
121/** 121/**
122 * Handles a pool of resources protected by fences. Manages resource overflow allocating more
123 * resources.
124 */
125class VKFencedPool {
126public:
127 explicit VKFencedPool(std::size_t grow_step);
128 virtual ~VKFencedPool();
129
130protected:
131 /**
132 * Commits a free resource and protects it with a fence. It may allocate new resources.
133 * @param fence Fence that protects the commited resource.
134 * @returns Index of the resource commited.
135 */
136 std::size_t CommitResource(VKFence& fence);
137
138 /// Called when a chunk of resources have to be allocated.
139 virtual void Allocate(std::size_t begin, std::size_t end) = 0;
140
141private:
142 /// Manages pool overflow allocating new resources.
143 std::size_t ManageOverflow();
144
145 /// Allocates a new page of resources.
146 void Grow();
147
148 std::size_t grow_step = 0; ///< Number of new resources created after an overflow
149 std::size_t free_iterator = 0; ///< Hint to where the next free resources is likely to be found
150 std::vector<std::unique_ptr<VKFenceWatch>> watches; ///< Set of watched resources
151};
152
153/**
122 * The resource manager handles all resources that can be protected with a fence avoiding 154 * 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. 155 * driver-side or GPU-side concurrent usage. Usage is documented in VKFence.
124 */ 156 */