vk_fence_manager: Initial implementation
This commit is contained in:
parent
0649f05900
commit
b752faf2d3
8 changed files with 222 additions and 12 deletions
|
@ -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 {
|
||||
|
|
Loading…
Reference in a new issue