vk_fence_manager: Initial implementation
This commit is contained in:
		
				
					committed by
					
						 Fernando Sahmkow
						Fernando Sahmkow
					
				
			
			
				
	
			
			
			
						parent
						
							0649f05900
						
					
				
				
					commit
					b752faf2d3
				
			| @@ -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 | ||||
|   | ||||
| @@ -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
									
								
								src/video_core/renderer_vulkan/vk_fence_manager.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								src/video_core/renderer_vulkan/vk_fence_manager.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -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
									
								
								src/video_core/renderer_vulkan/vk_fence_manager.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										74
									
								
								src/video_core/renderer_vulkan/vk_fence_manager.h
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| @@ -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) { | ||||
|   | ||||
| @@ -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; | ||||
|   | ||||
| @@ -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)); | ||||
|   | ||||
| @@ -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 { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user