From abd921934799f4cab433f076d5314605dc94cbff Mon Sep 17 00:00:00 2001 From: Flyinghead Date: Wed, 11 Oct 2023 09:35:18 +0200 Subject: [PATCH] vk oit: add sync event between renderer and vk context on Mali gpu Use vk event to wait for renderer pipeline to finish before rendering the final frame in vk context. This seems to help Mali gpus. Issue #1234 --- core/rend/vulkan/oit/oit_drawer.h | 11 ++++++++++- core/rend/vulkan/vk_context_lr.cpp | 2 +- core/rend/vulkan/vk_context_lr.h | 2 +- core/rend/vulkan/vulkan_context.cpp | 7 ++++++- core/rend/vulkan/vulkan_context.h | 2 +- 5 files changed, 19 insertions(+), 5 deletions(-) diff --git a/core/rend/vulkan/oit/oit_drawer.h b/core/rend/vulkan/oit/oit_drawer.h index 1c29ee2a3..383ef6a8c 100644 --- a/core/rend/vulkan/oit/oit_drawer.h +++ b/core/rend/vulkan/oit/oit_drawer.h @@ -165,12 +165,16 @@ public: screenPipelineManager = std::make_unique(); screenPipelineManager->Init(shaderManager, oitBuffers); OITDrawer::Init(samplerManager, screenPipelineManager.get(), oitBuffers); + if (GetContext()->GetVendorID() == VulkanContext::VENDOR_ARM) + // Use an event to synchronize command buffers with Mali GPUs + event = GetContext()->GetDevice().createEventUnique(vk::EventCreateInfo()); MakeFramebuffers(viewport); GetContext()->PresentFrame(vk::Image(), vk::ImageView(), viewport, 0); } void Term() { + event.reset(); screenPipelineManager.reset(); framebuffers.clear(); finalColorAttachments.clear(); @@ -188,6 +192,10 @@ public: } else { + if (event) { + GetContext()->GetDevice().resetEvent(*event); + currentCommandBuffer.setEvent(*event, vk::PipelineStageFlagBits::eBottomOfPipe); + } currentCommandBuffer.end(); commandPool->EndFrame(); aspectRatio = getOutputFramebufferAspectRatio(); @@ -203,7 +211,7 @@ public: return false; frameRendered = false; GetContext()->PresentFrame(finalColorAttachments[GetCurrentImage()]->GetImage(), - finalColorAttachments[GetCurrentImage()]->GetImageView(), viewport.extent, aspectRatio); + finalColorAttachments[GetCurrentImage()]->GetImageView(), viewport.extent, aspectRatio, *event); return true; } @@ -222,6 +230,7 @@ private: std::vector transitionNeeded; bool frameRendered = false; float aspectRatio = 0.f; + vk::UniqueEvent event; }; class OITTextureDrawer : public OITDrawer diff --git a/core/rend/vulkan/vk_context_lr.cpp b/core/rend/vulkan/vk_context_lr.cpp index 8daa7aaa7..5265c95b1 100644 --- a/core/rend/vulkan/vk_context_lr.cpp +++ b/core/rend/vulkan/vk_context_lr.cpp @@ -321,7 +321,7 @@ bool VulkanContext::init(retro_hw_render_interface_vulkan *retro_render_if) return true; } -void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) +void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio, vk::Event event) { if (image == vk::Image()) return; diff --git a/core/rend/vulkan/vk_context_lr.h b/core/rend/vulkan/vk_context_lr.h index 16edba20b..76039336d 100644 --- a/core/rend/vulkan/vk_context_lr.h +++ b/core/rend/vulkan/vk_context_lr.h @@ -43,7 +43,7 @@ public: void term() override; u32 GetGraphicsQueueFamilyIndex() const { return retro_render_if->queue_index; } - void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio); + void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio, vk::Event event = nullptr); vk::PhysicalDevice GetPhysicalDevice() const { return physicalDevice; } vk::Device GetDevice() const { return device; } diff --git a/core/rend/vulkan/vulkan_context.cpp b/core/rend/vulkan/vulkan_context.cpp index 18a194213..1677709e5 100644 --- a/core/rend/vulkan/vulkan_context.cpp +++ b/core/rend/vulkan/vulkan_context.cpp @@ -952,7 +952,7 @@ vk::CommandBuffer VulkanContext::PrepareOverlay(bool vmu, bool crosshair) extern Renderer *renderer; -void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) noexcept +void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio, vk::Event event) noexcept { lastFrameView = imageView; lastFrameExtent = extent; @@ -967,7 +967,12 @@ void VulkanContext::PresentFrame(vk::Image image, vk::ImageView imageView, const BeginRenderPass(); if (lastFrameView) // Might have been nullified if swap chain recreated + { + if (event) + GetCurrentCommandBuffer().waitEvents(event, vk::PipelineStageFlagBits::eBottomOfPipe, vk::PipelineStageFlagBits::eTopOfPipe, + nullptr, nullptr, nullptr); DrawFrame(imageView, extent, aspectRatio); + } DrawOverlay(settings.display.uiScale, config::FloatVMUs, true); renderer->DrawOSD(false); diff --git a/core/rend/vulkan/vulkan_context.h b/core/rend/vulkan/vulkan_context.h index cdff7e2cb..cbc109bfa 100644 --- a/core/rend/vulkan/vulkan_context.h +++ b/core/rend/vulkan/vulkan_context.h @@ -59,7 +59,7 @@ public: void BeginRenderPass(); void EndFrame(vk::CommandBuffer cmdBuffer = vk::CommandBuffer()); void Present() noexcept; - void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio) noexcept; + void PresentFrame(vk::Image image, vk::ImageView imageView, const vk::Extent2D& extent, float aspectRatio, vk::Event event = nullptr) noexcept; void PresentLastFrame(); void initVideoRouting() override;