Quellcode durchsuchen

vk_fence_manager: Initial implementation

ReinUsesLisp vor 6 Jahren
Ursprung
Commit
b752faf2d3

+ 2 - 0
src/video_core/CMakeLists.txt

@@ -177,6 +177,8 @@ if (ENABLE_VULKAN)
         renderer_vulkan/vk_descriptor_pool.h
         renderer_vulkan/vk_device.cpp
         renderer_vulkan/vk_device.h
+        renderer_vulkan/vk_fence_manager.cpp
+        renderer_vulkan/vk_fence_manager.h
         renderer_vulkan/vk_graphics_pipeline.cpp
         renderer_vulkan/vk_graphics_pipeline.h
         renderer_vulkan/vk_image.cpp

+ 1 - 0
src/video_core/buffer_cache/buffer_cache.h

@@ -19,6 +19,7 @@
 
 #include "common/alignment.h"
 #include "common/common_types.h"
+#include "common/logging/log.h"
 #include "core/core.h"
 #include "core/memory.h"
 #include "core/settings.h"

+ 101 - 0
src/video_core/renderer_vulkan/vk_fence_manager.cpp

@@ -0,0 +1,101 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <memory>
+#include <thread>
+
+#include "video_core/renderer_vulkan/vk_buffer_cache.h"
+#include "video_core/renderer_vulkan/vk_device.h"
+#include "video_core/renderer_vulkan/vk_fence_manager.h"
+#include "video_core/renderer_vulkan/vk_scheduler.h"
+#include "video_core/renderer_vulkan/vk_texture_cache.h"
+#include "video_core/renderer_vulkan/wrapper.h"
+
+namespace Vulkan {
+
+InnerFence::InnerFence(const VKDevice& device, VKScheduler& scheduler, u32 payload, bool is_stubbed)
+    : VideoCommon::FenceBase(payload, is_stubbed), device{device}, scheduler{scheduler} {}
+
+InnerFence::InnerFence(const VKDevice& device, VKScheduler& scheduler, GPUVAddr address,
+                       u32 payload, bool is_stubbed)
+    : VideoCommon::FenceBase(address, payload, is_stubbed), device{device}, scheduler{scheduler} {}
+
+InnerFence::~InnerFence() = default;
+
+void InnerFence::Queue() {
+    if (is_stubbed) {
+        return;
+    }
+    ASSERT(!event);
+
+    event = device.GetLogical().CreateEvent();
+    ticks = scheduler.Ticks();
+
+    scheduler.RequestOutsideRenderPassOperationContext();
+    scheduler.Record([event = *event](vk::CommandBuffer cmdbuf) {
+        cmdbuf.SetEvent(event, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
+    });
+}
+
+bool InnerFence::IsSignaled() const {
+    if (is_stubbed) {
+        return true;
+    }
+    ASSERT(event);
+    return IsEventSignalled();
+}
+
+void InnerFence::Wait() {
+    if (is_stubbed) {
+        return;
+    }
+    ASSERT(event);
+
+    if (ticks >= scheduler.Ticks()) {
+        scheduler.Flush();
+    }
+    while (!IsEventSignalled()) {
+        std::this_thread::yield();
+    }
+}
+
+bool InnerFence::IsEventSignalled() const {
+    switch (const VkResult result = event.GetStatus()) {
+    case VK_EVENT_SET:
+        return true;
+    case VK_EVENT_RESET:
+        return false;
+    default:
+        throw vk::Exception(result);
+    }
+}
+
+VKFenceManager::VKFenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
+                               const VKDevice& device, VKScheduler& scheduler,
+                               VKTextureCache& texture_cache, VKBufferCache& buffer_cache,
+                               VKQueryCache& query_cache)
+    : GenericFenceManager(system, rasterizer, texture_cache, buffer_cache, query_cache),
+      device{device}, scheduler{scheduler} {}
+
+Fence VKFenceManager::CreateFence(u32 value, bool is_stubbed) {
+    return std::make_shared<InnerFence>(device, scheduler, value, is_stubbed);
+}
+
+Fence VKFenceManager::CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) {
+    return std::make_shared<InnerFence>(device, scheduler, addr, value, is_stubbed);
+}
+
+void VKFenceManager::QueueFence(Fence& fence) {
+    fence->Queue();
+}
+
+bool VKFenceManager::IsFenceSignaled(Fence& fence) {
+    return fence->IsSignaled();
+}
+
+void VKFenceManager::WaitFence(Fence& fence) {
+    fence->Wait();
+}
+
+} // namespace Vulkan

+ 74 - 0
src/video_core/renderer_vulkan/vk_fence_manager.h

@@ -0,0 +1,74 @@
+// Copyright 2020 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <memory>
+
+#include "video_core/fence_manager.h"
+#include "video_core/renderer_vulkan/wrapper.h"
+
+namespace Core {
+class System;
+}
+
+namespace VideoCore {
+class RasterizerInterface;
+}
+
+namespace Vulkan {
+
+class VKBufferCache;
+class VKDevice;
+class VKQueryCache;
+class VKScheduler;
+class VKTextureCache;
+
+class InnerFence : public VideoCommon::FenceBase {
+public:
+    explicit InnerFence(const VKDevice& device, VKScheduler& scheduler, u32 payload,
+                        bool is_stubbed);
+    explicit InnerFence(const VKDevice& device, VKScheduler& scheduler, GPUVAddr address,
+                        u32 payload, bool is_stubbed);
+    ~InnerFence();
+
+    void Queue();
+
+    bool IsSignaled() const;
+
+    void Wait();
+
+private:
+    bool IsEventSignalled() const;
+
+    const VKDevice& device;
+    VKScheduler& scheduler;
+    vk::Event event;
+    u64 ticks = 0;
+};
+using Fence = std::shared_ptr<InnerFence>;
+
+using GenericFenceManager =
+    VideoCommon::FenceManager<Fence, VKTextureCache, VKBufferCache, VKQueryCache>;
+
+class VKFenceManager final : public GenericFenceManager {
+public:
+    explicit VKFenceManager(Core::System& system, VideoCore::RasterizerInterface& rasterizer,
+                            const VKDevice& device, VKScheduler& scheduler,
+                            VKTextureCache& texture_cache, VKBufferCache& buffer_cache,
+                            VKQueryCache& query_cache);
+
+protected:
+    Fence CreateFence(u32 value, bool is_stubbed) override;
+    Fence CreateFence(GPUVAddr addr, u32 value, bool is_stubbed) override;
+    void QueueFence(Fence& fence) override;
+    bool IsFenceSignaled(Fence& fence) override;
+    void WaitFence(Fence& fence) override;
+
+private:
+    const VKDevice& device;
+    VKScheduler& scheduler;
+};
+
+} // namespace Vulkan

+ 4 - 12
src/video_core/renderer_vulkan/vk_rasterizer.cpp

@@ -299,7 +299,9 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
       pipeline_cache(system, *this, device, scheduler, descriptor_pool, update_descriptor_queue,
                      renderpass_cache),
       buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool),
-      sampler_cache(device), query_cache(system, *this, device, scheduler) {
+      sampler_cache(device),
+      fence_manager(system, *this, device, scheduler, texture_cache, buffer_cache, query_cache),
+      query_cache(system, *this, device, scheduler) {
     scheduler.SetQueryCache(query_cache);
 }
 
@@ -547,38 +549,28 @@ void RasterizerVulkan::SyncGuestHost() {
 
 void RasterizerVulkan::SignalSemaphore(GPUVAddr addr, u32 value) {
     auto& gpu{system.GPU()};
-    auto& memory_manager{gpu.MemoryManager()};
-    memory_manager.Write<u32>(addr, value);
-    /*
     if (!gpu.IsAsync()) {
-        auto& memory_manager{gpu.MemoryManager()};
-        memory_manager.Write<u32>(addr, value);
+        gpu.MemoryManager().Write<u32>(addr, value);
         return;
     }
     fence_manager.SignalSemaphore(addr, value);
-    */
 }
 
 void RasterizerVulkan::SignalSyncPoint(u32 value) {
     auto& gpu{system.GPU()};
-    gpu.IncrementSyncPoint(value);
-    /*
     if (!gpu.IsAsync()) {
         gpu.IncrementSyncPoint(value);
         return;
     }
     fence_manager.SignalSyncPoint(value);
-    */
 }
 
 void RasterizerVulkan::ReleaseFences() {
-    /*
     auto& gpu{system.GPU()};
     if (!gpu.IsAsync()) {
         return;
     }
     fence_manager.WaitPendingFences();
-    */
 }
 
 void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) {

+ 2 - 0
src/video_core/renderer_vulkan/vk_rasterizer.h

@@ -21,6 +21,7 @@
 #include "video_core/renderer_vulkan/vk_buffer_cache.h"
 #include "video_core/renderer_vulkan/vk_compute_pass.h"
 #include "video_core/renderer_vulkan/vk_descriptor_pool.h"
+#include "video_core/renderer_vulkan/vk_fence_manager.h"
 #include "video_core/renderer_vulkan/vk_memory_manager.h"
 #include "video_core/renderer_vulkan/vk_pipeline_cache.h"
 #include "video_core/renderer_vulkan/vk_query_cache.h"
@@ -267,6 +268,7 @@ private:
     VKPipelineCache pipeline_cache;
     VKBufferCache buffer_cache;
     VKSamplerCache sampler_cache;
+    VKFenceManager fence_manager;
     VKQueryCache query_cache;
 
     std::array<View, Maxwell::NumRenderTargets> color_attachments;

+ 18 - 0
src/video_core/renderer_vulkan/wrapper.cpp

@@ -64,6 +64,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkCmdSetCheckpointNV);
     X(vkCmdSetDepthBias);
     X(vkCmdSetDepthBounds);
+    X(vkCmdSetEvent);
     X(vkCmdSetScissor);
     X(vkCmdSetStencilCompareMask);
     X(vkCmdSetStencilReference);
@@ -76,6 +77,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkCreateDescriptorPool);
     X(vkCreateDescriptorSetLayout);
     X(vkCreateDescriptorUpdateTemplateKHR);
+    X(vkCreateEvent);
     X(vkCreateFence);
     X(vkCreateFramebuffer);
     X(vkCreateGraphicsPipelines);
@@ -94,6 +96,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkDestroyDescriptorPool);
     X(vkDestroyDescriptorSetLayout);
     X(vkDestroyDescriptorUpdateTemplateKHR);
+    X(vkDestroyEvent);
     X(vkDestroyFence);
     X(vkDestroyFramebuffer);
     X(vkDestroyImage);
@@ -113,6 +116,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
     X(vkFreeMemory);
     X(vkGetBufferMemoryRequirements);
     X(vkGetDeviceQueue);
+    X(vkGetEventStatus);
     X(vkGetFenceStatus);
     X(vkGetImageMemoryRequirements);
     X(vkGetQueryPoolResults);
@@ -271,6 +275,10 @@ void Destroy(VkDevice device, VkDeviceMemory handle, const DeviceDispatch& dld)
     dld.vkFreeMemory(device, handle, nullptr);
 }
 
+void Destroy(VkDevice device, VkEvent handle, const DeviceDispatch& dld) noexcept {
+    dld.vkDestroyEvent(device, handle, nullptr);
+}
+
 void Destroy(VkDevice device, VkFence handle, const DeviceDispatch& dld) noexcept {
     dld.vkDestroyFence(device, handle, nullptr);
 }
@@ -613,6 +621,16 @@ ShaderModule Device::CreateShaderModule(const VkShaderModuleCreateInfo& ci) cons
     return ShaderModule(object, handle, *dld);
 }
 
+Event Device::CreateEvent() const {
+    VkEventCreateInfo ci;
+    ci.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
+    ci.pNext = nullptr;
+    ci.flags = 0;
+    VkEvent object;
+    Check(dld->vkCreateEvent(handle, &ci, nullptr, &object));
+    return Event(object, handle, *dld);
+}
+
 SwapchainKHR Device::CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const {
     VkSwapchainKHR object;
     Check(dld->vkCreateSwapchainKHR(handle, &ci, nullptr, &object));

+ 20 - 0
src/video_core/renderer_vulkan/wrapper.h

@@ -200,6 +200,7 @@ struct DeviceDispatch : public InstanceDispatch {
     PFN_vkCmdSetCheckpointNV vkCmdSetCheckpointNV;
     PFN_vkCmdSetDepthBias vkCmdSetDepthBias;
     PFN_vkCmdSetDepthBounds vkCmdSetDepthBounds;
+    PFN_vkCmdSetEvent vkCmdSetEvent;
     PFN_vkCmdSetScissor vkCmdSetScissor;
     PFN_vkCmdSetStencilCompareMask vkCmdSetStencilCompareMask;
     PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
@@ -212,6 +213,7 @@ struct DeviceDispatch : public InstanceDispatch {
     PFN_vkCreateDescriptorPool vkCreateDescriptorPool;
     PFN_vkCreateDescriptorSetLayout vkCreateDescriptorSetLayout;
     PFN_vkCreateDescriptorUpdateTemplateKHR vkCreateDescriptorUpdateTemplateKHR;
+    PFN_vkCreateEvent vkCreateEvent;
     PFN_vkCreateFence vkCreateFence;
     PFN_vkCreateFramebuffer vkCreateFramebuffer;
     PFN_vkCreateGraphicsPipelines vkCreateGraphicsPipelines;
@@ -230,6 +232,7 @@ struct DeviceDispatch : public InstanceDispatch {
     PFN_vkDestroyDescriptorPool vkDestroyDescriptorPool;
     PFN_vkDestroyDescriptorSetLayout vkDestroyDescriptorSetLayout;
     PFN_vkDestroyDescriptorUpdateTemplateKHR vkDestroyDescriptorUpdateTemplateKHR;
+    PFN_vkDestroyEvent vkDestroyEvent;
     PFN_vkDestroyFence vkDestroyFence;
     PFN_vkDestroyFramebuffer vkDestroyFramebuffer;
     PFN_vkDestroyImage vkDestroyImage;
@@ -249,6 +252,7 @@ struct DeviceDispatch : public InstanceDispatch {
     PFN_vkFreeMemory vkFreeMemory;
     PFN_vkGetBufferMemoryRequirements vkGetBufferMemoryRequirements;
     PFN_vkGetDeviceQueue vkGetDeviceQueue;
+    PFN_vkGetEventStatus vkGetEventStatus;
     PFN_vkGetFenceStatus vkGetFenceStatus;
     PFN_vkGetImageMemoryRequirements vkGetImageMemoryRequirements;
     PFN_vkGetQueryPoolResults vkGetQueryPoolResults;
@@ -281,6 +285,7 @@ void Destroy(VkDevice, VkDescriptorPool, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkDescriptorSetLayout, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkDescriptorUpdateTemplateKHR, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkDeviceMemory, const DeviceDispatch&) noexcept;
+void Destroy(VkDevice, VkEvent, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkFence, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkFramebuffer, const DeviceDispatch&) noexcept;
 void Destroy(VkDevice, VkImage, const DeviceDispatch&) noexcept;
@@ -654,6 +659,15 @@ public:
     std::vector<VkImage> GetImages() const;
 };
 
+class Event : public Handle<VkEvent, VkDevice, DeviceDispatch> {
+    using Handle<VkEvent, VkDevice, DeviceDispatch>::Handle;
+
+public:
+    VkResult GetStatus() const noexcept {
+        return dld->vkGetEventStatus(owner, handle);
+    }
+};
+
 class Device : public Handle<VkDevice, NoOwner, DeviceDispatch> {
     using Handle<VkDevice, NoOwner, DeviceDispatch>::Handle;
 
@@ -702,6 +716,8 @@ public:
 
     ShaderModule CreateShaderModule(const VkShaderModuleCreateInfo& ci) const;
 
+    Event CreateEvent() const;
+
     SwapchainKHR CreateSwapchainKHR(const VkSwapchainCreateInfoKHR& ci) const;
 
     DeviceMemory TryAllocateMemory(const VkMemoryAllocateInfo& ai) const noexcept;
@@ -956,6 +972,10 @@ public:
         dld->vkCmdSetDepthBounds(handle, min_depth_bounds, max_depth_bounds);
     }
 
+    void SetEvent(VkEvent event, VkPipelineStageFlags stage_flags) const noexcept {
+        dld->vkCmdSetEvent(handle, event, stage_flags);
+    }
+
     void BindTransformFeedbackBuffersEXT(u32 first, u32 count, const VkBuffer* buffers,
                                          const VkDeviceSize* offsets,
                                          const VkDeviceSize* sizes) const noexcept {