summaryrefslogtreecommitdiffstats
path: root/src/video_core/renderer_vulkan/vk_resource_manager.cpp
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2019-02-14 17:35:03 +0100
committerReinUsesLisp <reinuseslisp@airmail.cc>2019-02-14 22:44:26 +0100
commita2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6 (patch)
tree5eda182bf4ddc84adb9e5465ac4e17c5c3a51133 /src/video_core/renderer_vulkan/vk_resource_manager.cpp
parentvk_resource_manager: Implement VKResourceManager and fence allocator (diff)
downloadyuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar.gz
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar.bz2
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar.lz
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar.xz
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.tar.zst
yuzu-a2b6de7e9fd2a2e4956a83a16ded12f3ccfa0ed6.zip
Diffstat (limited to 'src/video_core/renderer_vulkan/vk_resource_manager.cpp')
-rw-r--r--src/video_core/renderer_vulkan/vk_resource_manager.cpp51
1 files changed, 51 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 @@
// Refer to the license.txt file included.
#include <algorithm>
+#include <optional>
#include "common/assert.h"
#include "common/logging/log.h"
#include "video_core/renderer_vulkan/declarations.h"
@@ -121,6 +122,56 @@ void VKFenceWatch::OnFenceRemoval(VKFence* signaling_fence) {
fence = nullptr;
}
+VKFencedPool::VKFencedPool(std::size_t grow_step) : grow_step{grow_step} {}
+
+VKFencedPool::~VKFencedPool() = default;
+
+std::size_t VKFencedPool::CommitResource(VKFence& fence) {
+ const auto Search = [&](std::size_t begin, std::size_t end) -> std::optional<std::size_t> {
+ for (std::size_t iterator = begin; iterator < end; ++iterator) {
+ if (watches[iterator]->TryWatch(fence)) {
+ // The resource is now being watched, a free resource was successfully found.
+ return iterator;
+ }
+ }
+ return {};
+ };
+ // Try to find a free resource from the hinted position to the end.
+ auto found = Search(free_iterator, watches.size());
+ if (!found) {
+ // Search from beginning to the hinted position.
+ found = Search(0, free_iterator);
+ if (!found) {
+ // Both searches failed, the pool is full; handle it.
+ const std::size_t free_resource = ManageOverflow();
+
+ // Watch will wait for the resource to be free.
+ watches[free_resource]->Watch(fence);
+ found = free_resource;
+ }
+ }
+ // Free iterator is hinted to the resource after the one that's been commited.
+ free_iterator = (*found + 1) % watches.size();
+ return *found;
+}
+
+std::size_t VKFencedPool::ManageOverflow() {
+ const std::size_t old_capacity = watches.size();
+ Grow();
+
+ // The last entry is guaranted to be free, since it's the first element of the freshly
+ // allocated resources.
+ return old_capacity;
+}
+
+void VKFencedPool::Grow() {
+ const std::size_t old_capacity = watches.size();
+ watches.resize(old_capacity + grow_step);
+ std::generate(watches.begin() + old_capacity, watches.end(),
+ []() { return std::make_unique<VKFenceWatch>(); });
+ Allocate(old_capacity, old_capacity + grow_step);
+}
+
VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} {
GrowFences(FENCES_GROW_STEP);
}