summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar GPUCode2023-05-20 14:08:05 +0300
committerGravatar GPUCode2023-05-20 19:23:53 +0300
commit4e491ab59ba8b9c08253ca9cce5bb9fe909ac2ff (patch)
tree1a371195bf04722d77c01ec624224adc517ce7a3
parentMerge pull request #10344 from german77/pro-amiibo (diff)
downloadyuzu-4e491ab59ba8b9c08253ca9cce5bb9fe909ac2ff.tar.gz
yuzu-4e491ab59ba8b9c08253ca9cce5bb9fe909ac2ff.tar.xz
yuzu-4e491ab59ba8b9c08253ca9cce5bb9fe909ac2ff.zip
vk_master_semaphore: Move fence wait on separate thread
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.cpp46
-rw-r--r--src/video_core/renderer_vulkan/vk_master_semaphore.h15
2 files changed, 58 insertions, 3 deletions
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
index 47c74e4d8..8b65aeaeb 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.cpp
@@ -10,11 +10,16 @@
10 10
11namespace Vulkan { 11namespace Vulkan {
12 12
13constexpr u64 FENCE_RESERVE_SIZE = 8;
14
13MasterSemaphore::MasterSemaphore(const Device& device_) : device(device_) { 15MasterSemaphore::MasterSemaphore(const Device& device_) : device(device_) {
14 if (!device.HasTimelineSemaphore()) { 16 if (!device.HasTimelineSemaphore()) {
15 static constexpr VkFenceCreateInfo fence_ci{ 17 static constexpr VkFenceCreateInfo fence_ci{
16 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0}; 18 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0};
17 fence = device.GetLogical().CreateFence(fence_ci); 19 free_queue.resize(FENCE_RESERVE_SIZE);
20 std::ranges::generate(free_queue,
21 [&] { return device.GetLogical().CreateFence(fence_ci); });
22 wait_thread = std::jthread([this](std::stop_token token) { WaitThread(token); });
18 return; 23 return;
19 } 24 }
20 25
@@ -167,16 +172,53 @@ VkResult MasterSemaphore::SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphor
167 .pSignalSemaphores = &signal_semaphore, 172 .pSignalSemaphores = &signal_semaphore,
168 }; 173 };
169 174
175 auto fence = GetFreeFence();
170 auto result = device.GetGraphicsQueue().Submit(submit_info, *fence); 176 auto result = device.GetGraphicsQueue().Submit(submit_info, *fence);
171 177
172 if (result == VK_SUCCESS) { 178 if (result == VK_SUCCESS) {
179 std::scoped_lock lock{wait_mutex};
180 wait_queue.emplace(host_tick, std::move(fence));
181 wait_cv.notify_one();
182 }
183
184 return result;
185}
186
187void MasterSemaphore::WaitThread(std::stop_token token) {
188 while (!token.stop_requested()) {
189 u64 host_tick;
190 vk::Fence fence;
191 {
192 std::unique_lock lock{wait_mutex};
193 Common::CondvarWait(wait_cv, lock, token, [this] { return !wait_queue.empty(); });
194 if (token.stop_requested()) {
195 return;
196 }
197 std::tie(host_tick, fence) = std::move(wait_queue.front());
198 wait_queue.pop();
199 }
200
173 fence.Wait(); 201 fence.Wait();
174 fence.Reset(); 202 fence.Reset();
175 gpu_tick.store(host_tick); 203 gpu_tick.store(host_tick);
176 gpu_tick.notify_all(); 204 gpu_tick.notify_all();
205
206 std::scoped_lock lock{free_mutex};
207 free_queue.push_front(std::move(fence));
177 } 208 }
209}
178 210
179 return result; 211vk::Fence MasterSemaphore::GetFreeFence() {
212 std::scoped_lock lock{free_mutex};
213 if (free_queue.empty()) {
214 static constexpr VkFenceCreateInfo fence_ci{
215 .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, .pNext = nullptr, .flags = 0};
216 return device.GetLogical().CreateFence(fence_ci);
217 }
218
219 auto fence = std::move(free_queue.back());
220 free_queue.pop_back();
221 return fence;
180} 222}
181 223
182} // namespace Vulkan 224} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/vk_master_semaphore.h b/src/video_core/renderer_vulkan/vk_master_semaphore.h
index f2f61f781..1e7c90215 100644
--- a/src/video_core/renderer_vulkan/vk_master_semaphore.h
+++ b/src/video_core/renderer_vulkan/vk_master_semaphore.h
@@ -5,8 +5,10 @@
5 5
6#include <atomic> 6#include <atomic>
7#include <condition_variable> 7#include <condition_variable>
8#include <deque>
8#include <mutex> 9#include <mutex>
9#include <thread> 10#include <thread>
11#include <queue>
10 12
11#include "common/common_types.h" 13#include "common/common_types.h"
12#include "common/polyfill_thread.h" 14#include "common/polyfill_thread.h"
@@ -17,6 +19,8 @@ namespace Vulkan {
17class Device; 19class Device;
18 20
19class MasterSemaphore { 21class MasterSemaphore {
22 using Waitable = std::pair<u64, vk::Fence>;
23
20public: 24public:
21 explicit MasterSemaphore(const Device& device); 25 explicit MasterSemaphore(const Device& device);
22 ~MasterSemaphore(); 26 ~MasterSemaphore();
@@ -57,13 +61,22 @@ private:
57 VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore, 61 VkResult SubmitQueueFence(vk::CommandBuffer& cmdbuf, VkSemaphore signal_semaphore,
58 VkSemaphore wait_semaphore, u64 host_tick); 62 VkSemaphore wait_semaphore, u64 host_tick);
59 63
64 void WaitThread(std::stop_token token);
65
66 vk::Fence GetFreeFence();
67
60private: 68private:
61 const Device& device; ///< Device. 69 const Device& device; ///< Device.
62 vk::Fence fence; ///< Fence.
63 vk::Semaphore semaphore; ///< Timeline semaphore. 70 vk::Semaphore semaphore; ///< Timeline semaphore.
64 std::atomic<u64> gpu_tick{0}; ///< Current known GPU tick. 71 std::atomic<u64> gpu_tick{0}; ///< Current known GPU tick.
65 std::atomic<u64> current_tick{1}; ///< Current logical tick. 72 std::atomic<u64> current_tick{1}; ///< Current logical tick.
73 std::mutex wait_mutex;
74 std::mutex free_mutex;
75 std::condition_variable_any wait_cv;
76 std::queue<Waitable> wait_queue; ///< Queue for the fences to be waited on by the wait thread.
77 std::deque<vk::Fence> free_queue; ///< Holds available fences for submission.
66 std::jthread debug_thread; ///< Debug thread to workaround validation layer bugs. 78 std::jthread debug_thread; ///< Debug thread to workaround validation layer bugs.
79 std::jthread wait_thread; ///< Helper thread that waits for submitted fences.
67}; 80};
68 81
69} // namespace Vulkan 82} // namespace Vulkan