diff options
| author | 2019-02-14 13:11:32 -0300 | |
|---|---|---|
| committer | 2019-02-14 18:44:26 -0300 | |
| commit | 0ffdd0a68367770a42455c2a523766d3d57210d1 (patch) | |
| tree | 979f19d79897bd924e406c13a177617aeddee415 /src | |
| parent | vk_resource_manager: Implement VKFenceWatch (diff) | |
| download | yuzu-0ffdd0a68367770a42455c2a523766d3d57210d1.tar.gz yuzu-0ffdd0a68367770a42455c2a523766d3d57210d1.tar.xz yuzu-0ffdd0a68367770a42455c2a523766d3d57210d1.zip | |
vk_resource_manager: Implement VKResourceManager and fence allocator
CommitFence iterates a pool of fences until one is found. If all fences
are being used at the same time, allocate more.
Diffstat (limited to '')
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_manager.cpp | 62 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_resource_manager.h | 23 |
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 | ||
| 11 | namespace Vulkan { | 12 | namespace Vulkan { |
| 12 | 13 | ||
| 14 | // TODO(Rodrigo): Fine tune these numbers. | ||
| 15 | constexpr std::size_t FENCES_GROW_STEP = 0x40; | ||
| 16 | |||
| 13 | VKResource::VKResource() = default; | 17 | VKResource::VKResource() = default; |
| 14 | 18 | ||
| 15 | VKResource::~VKResource() = default; | 19 | VKResource::~VKResource() = default; |
| @@ -117,4 +121,62 @@ void VKFenceWatch::OnFenceRemoval(VKFence* signaling_fence) { | |||
| 117 | fence = nullptr; | 121 | fence = nullptr; |
| 118 | } | 122 | } |
| 119 | 123 | ||
| 124 | VKResourceManager::VKResourceManager(const VKDevice& device) : device{device} { | ||
| 125 | GrowFences(FENCES_GROW_STEP); | ||
| 126 | } | ||
| 127 | |||
| 128 | VKResourceManager::~VKResourceManager() = default; | ||
| 129 | |||
| 130 | VKFence& 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 | |||
| 169 | void 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 | */ | ||
| 125 | class VKResourceManager final { | ||
| 126 | public: | ||
| 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 | |||
| 133 | private: | ||
| 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 |