{maxwell_3d,buffer_cache}: Implement memory barriers using 3D registers
Drop MemoryBarrier from the buffer cache and use Maxwell3D's register WaitForIdle. To implement this on OpenGL we just call glMemoryBarrier with the necessary bits. Vulkan lacks this synchronization primitive, so we set an event and immediately wait for it. This is not a pretty solution, but it's what Vulkan can do without submitting the current command buffer to the queue (which ends up being more expensive on the CPU).
This commit is contained in:
parent
1517cba8ca
commit
fe931ac976
13 changed files with 57 additions and 16 deletions
|
@ -55,8 +55,6 @@ public:
|
|||
protected:
|
||||
VkBuffer ToHandle(const Buffer& buffer) override;
|
||||
|
||||
void WriteBarrier() override {}
|
||||
|
||||
Buffer CreateBlock(VAddr cpu_addr, std::size_t size) override;
|
||||
|
||||
void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size,
|
||||
|
|
|
@ -302,7 +302,7 @@ RasterizerVulkan::RasterizerVulkan(Core::System& system, Core::Frontend::EmuWind
|
|||
buffer_cache(*this, system, device, memory_manager, scheduler, staging_pool),
|
||||
sampler_cache(device),
|
||||
fence_manager(system, *this, device, scheduler, texture_cache, buffer_cache, query_cache),
|
||||
query_cache(system, *this, device, scheduler) {
|
||||
query_cache(system, *this, device, scheduler), wfi_event{device.GetLogical().CreateEvent()} {
|
||||
scheduler.SetQueryCache(query_cache);
|
||||
}
|
||||
|
||||
|
@ -576,6 +576,26 @@ void RasterizerVulkan::FlushAndInvalidateRegion(VAddr addr, u64 size) {
|
|||
InvalidateRegion(addr, size);
|
||||
}
|
||||
|
||||
void RasterizerVulkan::WaitForIdle() {
|
||||
// Everything but wait pixel operations. This intentionally includes FRAGMENT_SHADER_BIT because
|
||||
// fragment shaders can still write storage buffers.
|
||||
VkPipelineStageFlags flags =
|
||||
VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT |
|
||||
VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
|
||||
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||
if (device.IsExtTransformFeedbackSupported()) {
|
||||
flags |= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT;
|
||||
}
|
||||
|
||||
scheduler.RequestOutsideRenderPassOperationContext();
|
||||
scheduler.Record([event = *wfi_event, flags](vk::CommandBuffer cmdbuf) {
|
||||
cmdbuf.SetEvent(event, flags);
|
||||
cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {});
|
||||
});
|
||||
}
|
||||
|
||||
void RasterizerVulkan::FlushCommands() {
|
||||
if (draw_counter > 0) {
|
||||
draw_counter = 0;
|
||||
|
|
|
@ -127,6 +127,7 @@ public:
|
|||
void SignalSyncPoint(u32 value) override;
|
||||
void ReleaseFences() override;
|
||||
void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
|
||||
void WaitForIdle() override;
|
||||
void FlushCommands() override;
|
||||
void TickFrame() override;
|
||||
bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
|
||||
|
@ -276,6 +277,7 @@ private:
|
|||
|
||||
vk::Buffer default_buffer;
|
||||
VKMemoryCommit default_buffer_commit;
|
||||
vk::Event wfi_event;
|
||||
|
||||
std::array<View, Maxwell::NumRenderTargets> color_attachments;
|
||||
View zeta_attachment;
|
||||
|
|
|
@ -87,6 +87,7 @@ void Load(VkDevice device, DeviceDispatch& dld) noexcept {
|
|||
X(vkCmdSetStencilReference);
|
||||
X(vkCmdSetStencilWriteMask);
|
||||
X(vkCmdSetViewport);
|
||||
X(vkCmdWaitEvents);
|
||||
X(vkCreateBuffer);
|
||||
X(vkCreateBufferView);
|
||||
X(vkCreateCommandPool);
|
||||
|
|
|
@ -205,6 +205,7 @@ struct DeviceDispatch : public InstanceDispatch {
|
|||
PFN_vkCmdSetStencilReference vkCmdSetStencilReference;
|
||||
PFN_vkCmdSetStencilWriteMask vkCmdSetStencilWriteMask;
|
||||
PFN_vkCmdSetViewport vkCmdSetViewport;
|
||||
PFN_vkCmdWaitEvents vkCmdWaitEvents;
|
||||
PFN_vkCreateBuffer vkCreateBuffer;
|
||||
PFN_vkCreateBufferView vkCreateBufferView;
|
||||
PFN_vkCreateCommandPool vkCreateCommandPool;
|
||||
|
@ -958,6 +959,15 @@ public:
|
|||
dld->vkCmdSetEvent(handle, event, stage_flags);
|
||||
}
|
||||
|
||||
void WaitEvents(Span<VkEvent> events, VkPipelineStageFlags src_stage_mask,
|
||||
VkPipelineStageFlags dst_stage_mask, Span<VkMemoryBarrier> memory_barriers,
|
||||
Span<VkBufferMemoryBarrier> buffer_barriers,
|
||||
Span<VkImageMemoryBarrier> image_barriers) const noexcept {
|
||||
dld->vkCmdWaitEvents(handle, events.size(), events.data(), src_stage_mask, dst_stage_mask,
|
||||
memory_barriers.size(), memory_barriers.data(), buffer_barriers.size(),
|
||||
buffer_barriers.data(), image_barriers.size(), image_barriers.data());
|
||||
}
|
||||
|
||||
void BindTransformFeedbackBuffersEXT(u32 first, u32 count, const VkBuffer* buffers,
|
||||
const VkDeviceSize* offsets,
|
||||
const VkDeviceSize* sizes) const noexcept {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue