summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-01-08 02:37:02 -0300
committerGravatar ReinUsesLisp2021-01-08 02:47:28 -0300
commit154a7653f9705ebee095b8f10609fd0f3f9ca394 (patch)
treebfc96a22372b307e3943c65fb3fb904f7c17f131 /src
parentMerge pull request #5237 from ameerj/nvdec-syncpt (diff)
downloadyuzu-154a7653f9705ebee095b8f10609fd0f3f9ca394.tar.gz
yuzu-154a7653f9705ebee095b8f10609fd0f3f9ca394.tar.xz
yuzu-154a7653f9705ebee095b8f10609fd0f3f9ca394.zip
vk_fence_manager: Use timeline semaphores instead of spin waits
With timeline semaphores we can avoid creating objects. Instead of creating an event, grab the current tick from the scheduler and flush the current command buffer. When the fence has to be queried/waited, we can do so against the master semaphore instead of spinning on an event. If Vulkan supported NVN like events or fences, we could signal from the command buffer and wait for that without splitting things in two separate command buffers.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.cpp54
-rw-r--r--src/video_core/renderer_vulkan/vk_fence_manager.h15
-rw-r--r--src/video_core/renderer_vulkan/vk_rasterizer.cpp3
3 files changed, 18 insertions, 54 deletions
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
index 4c5bc0aa1..6cd00884d 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <memory> 5#include <memory>
6#include <thread>
7 6
8#include "video_core/renderer_vulkan/vk_buffer_cache.h" 7#include "video_core/renderer_vulkan/vk_buffer_cache.h"
9#include "video_core/renderer_vulkan/vk_fence_manager.h" 8#include "video_core/renderer_vulkan/vk_fence_manager.h"
@@ -14,13 +13,11 @@
14 13
15namespace Vulkan { 14namespace Vulkan {
16 15
17InnerFence::InnerFence(const Device& device_, VKScheduler& scheduler_, u32 payload_, 16InnerFence::InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_)
18 bool is_stubbed_) 17 : FenceBase{payload_, is_stubbed_}, scheduler{scheduler_} {}
19 : FenceBase{payload_, is_stubbed_}, device{device_}, scheduler{scheduler_} {}
20 18
21InnerFence::InnerFence(const Device& device_, VKScheduler& scheduler_, GPUVAddr address_, 19InnerFence::InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_)
22 u32 payload_, bool is_stubbed_) 20 : FenceBase{address_, payload_, is_stubbed_}, scheduler{scheduler_} {}
23 : FenceBase{address_, payload_, is_stubbed_}, device{device_}, scheduler{scheduler_} {}
24 21
25InnerFence::~InnerFence() = default; 22InnerFence::~InnerFence() = default;
26 23
@@ -28,63 +25,38 @@ void InnerFence::Queue() {
28 if (is_stubbed) { 25 if (is_stubbed) {
29 return; 26 return;
30 } 27 }
31 ASSERT(!event); 28 // Get the current tick so we can wait for it
32 29 wait_tick = scheduler.CurrentTick();
33 event = device.GetLogical().CreateEvent(); 30 scheduler.Flush();
34 ticks = scheduler.CurrentTick();
35
36 scheduler.RequestOutsideRenderPassOperationContext();
37 scheduler.Record([event = *event](vk::CommandBuffer cmdbuf) {
38 cmdbuf.SetEvent(event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
39 });
40} 31}
41 32
42bool InnerFence::IsSignaled() const { 33bool InnerFence::IsSignaled() const {
43 if (is_stubbed) { 34 if (is_stubbed) {
44 return true; 35 return true;
45 } 36 }
46 ASSERT(event); 37 return scheduler.IsFree(wait_tick);
47 return IsEventSignalled();
48} 38}
49 39
50void InnerFence::Wait() { 40void InnerFence::Wait() {
51 if (is_stubbed) { 41 if (is_stubbed) {
52 return; 42 return;
53 } 43 }
54 ASSERT(event); 44 scheduler.Wait(wait_tick);
55
56 if (ticks >= scheduler.CurrentTick()) {
57 scheduler.Flush();
58 }
59 while (!IsEventSignalled()) {
60 std::this_thread::yield();
61 }
62}
63
64bool InnerFence::IsEventSignalled() const {
65 switch (const VkResult result = event.GetStatus()) {
66 case VK_EVENT_SET:
67 return true;
68 case VK_EVENT_RESET:
69 return false;
70 default:
71 throw vk::Exception(result);
72 }
73} 45}
74 46
75VKFenceManager::VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_, 47VKFenceManager::VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_,
76 Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_, 48 Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_,
77 VKBufferCache& buffer_cache_, VKQueryCache& query_cache_, 49 VKBufferCache& buffer_cache_, VKQueryCache& query_cache_,
78 const Device& device_, VKScheduler& scheduler_) 50 VKScheduler& scheduler_)
79 : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_}, 51 : GenericFenceManager{rasterizer_, gpu_, texture_cache_, buffer_cache_, query_cache_},
80 device{device_}, scheduler{scheduler_} {} 52 scheduler{scheduler_} {}
81 53
82Fence VKFenceManager::CreateFence(u32 value, bool is_stubbed) { 54Fence VKFenceManager::CreateFence(u32 value, bool is_stubbed) {
83 return std::make_shared<InnerFence>(device, scheduler, value, is_stubbed); 55 return std::make_shared<InnerFence>(scheduler, value, is_stubbed);
84} 56}
85 57
86Fence VKFenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) { 58Fence VKFenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
87 return std::make_shared<InnerFence>(device, scheduler, addr, value, is_stubbed); 59 return std::make_shared<InnerFence>(scheduler, addr, value, is_stubbed);
88} 60}
89 61
90void VKFenceManager::QueueFence(Fence& fence) { 62void VKFenceManager::QueueFence(Fence& fence) {
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h
index 6b51e4587..9c5e5aa8f 100644
--- a/src/video_core/renderer_vulkan/vk_fence_manager.h
+++ b/src/video_core/renderer_vulkan/vk_fence_manager.h
@@ -28,10 +28,8 @@ class VKScheduler;
28 28
29class InnerFence : public VideoCommon::FenceBase { 29class InnerFence : public VideoCommon::FenceBase {
30public: 30public:
31 explicit InnerFence(const Device& device_, VKScheduler& scheduler_, u32 payload_, 31 explicit InnerFence(VKScheduler& scheduler_, u32 payload_, bool is_stubbed_);
32 bool is_stubbed_); 32 explicit InnerFence(VKScheduler& scheduler_, GPUVAddr address_, u32 payload_, bool is_stubbed_);
33 explicit InnerFence(const Device& device_, VKScheduler& scheduler_, GPUVAddr address_,
34 u32 payload_, bool is_stubbed_);
35 ~InnerFence(); 33 ~InnerFence();
36 34
37 void Queue(); 35 void Queue();
@@ -41,12 +39,8 @@ public:
41 void Wait(); 39 void Wait();
42 40
43private: 41private:
44 bool IsEventSignalled() const;
45
46 const Device& device;
47 VKScheduler& scheduler; 42 VKScheduler& scheduler;
48 vk::Event event; 43 u64 wait_tick = 0;
49 u64 ticks = 0;
50}; 44};
51using Fence = std::shared_ptr<InnerFence>; 45using Fence = std::shared_ptr<InnerFence>;
52 46
@@ -58,7 +52,7 @@ public:
58 explicit VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_, 52 explicit VKFenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_,
59 Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_, 53 Tegra::MemoryManager& memory_manager_, TextureCache& texture_cache_,
60 VKBufferCache& buffer_cache_, VKQueryCache& query_cache_, 54 VKBufferCache& buffer_cache_, VKQueryCache& query_cache_,
61 const Device& device_, VKScheduler& scheduler_); 55 VKScheduler& scheduler_);
62 56
63protected: 57protected:
64 Fence CreateFence(u32 value, bool is_stubbed) override; 58 Fence CreateFence(u32 value, bool is_stubbed) override;
@@ -68,7 +62,6 @@ protected:
68 void WaitFence(Fence& fence) override; 62 void WaitFence(Fence& fence) override;
69 63
70private: 64private:
71 const Device& device;
72 VKScheduler& scheduler; 65 VKScheduler& scheduler;
73}; 66};
74 67
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
index 93fbea510..ce3db49bd 100644
--- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp
+++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp
@@ -428,8 +428,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra
428 buffer_cache(*this, gpu_memory, cpu_memory_, device, memory_manager, scheduler, stream_buffer, 428 buffer_cache(*this, gpu_memory, cpu_memory_, device, memory_manager, scheduler, stream_buffer,
429 staging_pool), 429 staging_pool),
430 query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, 430 query_cache{*this, maxwell3d, gpu_memory, device, scheduler},
431 fence_manager(*this, gpu, gpu_memory, texture_cache, buffer_cache, query_cache, device, 431 fence_manager(*this, gpu, gpu_memory, texture_cache, buffer_cache, query_cache, scheduler),
432 scheduler),
433 wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) { 432 wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) {
434 scheduler.SetQueryCache(query_cache); 433 scheduler.SetQueryCache(query_cache);
435 if (device.UseAsynchronousShaders()) { 434 if (device.UseAsynchronousShaders()) {