From 502dc1cbf38bc38d7f5d232d9651757754c677e2 Mon Sep 17 00:00:00 2001 From: IndecisiveTurtle <47210458+raphaelthegreat@users.noreply.github.com> Date: Sat, 13 Jul 2024 18:17:49 +0300 Subject: [PATCH] driver: Make flip blocking --- src/core/libraries/gnmdriver/gnmdriver.cpp | 2 +- src/core/libraries/videoout/driver.cpp | 9 +++++++++ src/video_core/amdgpu/liverpool.cpp | 10 ---------- .../renderer_vulkan/renderer_vulkan.cpp | 15 +++++++-------- src/video_core/renderer_vulkan/renderer_vulkan.h | 4 +++- 5 files changed, 20 insertions(+), 20 deletions(-) diff --git a/src/core/libraries/gnmdriver/gnmdriver.cpp b/src/core/libraries/gnmdriver/gnmdriver.cpp index dba69d6eb..a4e63f555 100644 --- a/src/core/libraries/gnmdriver/gnmdriver.cpp +++ b/src/core/libraries/gnmdriver/gnmdriver.cpp @@ -296,7 +296,7 @@ static void ResetSubmissionLock(Platform::InterruptId irq) { cv_lock.notify_all(); } -static void WaitGpuIdle() { +void WaitGpuIdle() { HLE_TRACE; std::unique_lock lock{m_submission}; cv_lock.wait(lock, [] { return submission_lock == 0; }); diff --git a/src/core/libraries/videoout/driver.cpp b/src/core/libraries/videoout/driver.cpp index 1c2b747a0..5e5f72254 100644 --- a/src/core/libraries/videoout/driver.cpp +++ b/src/core/libraries/videoout/driver.cpp @@ -12,6 +12,10 @@ extern std::unique_ptr renderer; extern std::unique_ptr liverpool; +namespace Libraries::GnmDriver { +void WaitGpuIdle(); +} + namespace Libraries::VideoOut { constexpr static bool Is32BppPixelFormat(PixelFormat format) { @@ -189,6 +193,11 @@ bool VideoOutDriver::SubmitFlip(VideoOutPort* port, s32 index, s64 flip_arg, bool is_eop /*= false*/) { std::scoped_lock lock{mutex}; + if (!is_eop) { + liverpool->SubmitDone(); + GnmDriver::WaitGpuIdle(); + } + Vulkan::Frame* frame; if (index == -1) { frame = renderer->PrepareBlankFrame(); diff --git a/src/video_core/amdgpu/liverpool.cpp b/src/video_core/amdgpu/liverpool.cpp index 56a2c63e7..7cdf9a4f4 100644 --- a/src/video_core/amdgpu/liverpool.cpp +++ b/src/video_core/amdgpu/liverpool.cpp @@ -362,11 +362,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::span(header); - // Guest can wait for GfxEop event to submit CPU flips. - // Flush command list to ensure order. - if (rasterizer && event_eop->int_sel == InterruptSelect::IrqWhenWriteConfirm) { - rasterizer->Flush(); - } event_eop->SignalFence(); break; } @@ -380,11 +375,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span dcb, std::spantype3.count.Value() - 2) * 4; u64* address = write_data->Address(); if (!write_data->wr_one_addr.Value()) { - // Guest can poll VO label before submitting CPU flips. - // Flush command list before signalling to ensure order. - if (rasterizer && vo_port->IsVoLabel(address)) { - rasterizer->Flush(); - } std::memcpy(address, write_data->data, data_size); } else { UNREACHABLE(); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index f28bfffc4..9bc9006d6 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp @@ -65,10 +65,9 @@ bool CanBlitToSwapchain(const vk::PhysicalDevice physical_device, vk::Format for RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* liverpool_) : window{window_}, liverpool{liverpool_}, instance{window, Config::getGpuId(), Config::vkValidationEnabled()}, - schedulers{Scheduler{instance}, Scheduler{instance}, Scheduler{instance}}, - swapchain{instance, window}, texture_cache{instance, schedulers[SchedulerType::Draw]} { - rasterizer = std::make_unique(instance, schedulers[SchedulerType::Draw], - texture_cache, liverpool); + draw_scheduler{instance}, present_scheduler{instance}, flip_scheduler{instance}, + swapchain{instance, window}, texture_cache{instance, draw_scheduler} { + rasterizer = std::make_unique(instance, draw_scheduler, texture_cache, liverpool); const u32 num_images = swapchain.GetImageCount(); const vk::Device device = instance.GetDevice(); @@ -82,7 +81,7 @@ RendererVulkan::RendererVulkan(Frontend::WindowSDL& window_, AmdGpu::Liverpool* } RendererVulkan::~RendererVulkan() { - schedulers[SchedulerType::Draw].Finish(); + draw_scheduler.Finish(); const vk::Device device = instance.GetDevice(); for (auto& frame : present_frames) { vmaDestroyImage(instance.GetAllocator(), frame.image, frame.allocation); @@ -170,7 +169,7 @@ bool RendererVulkan::ShowSplash(Frame* frame /*= nullptr*/) { info.pitch = splash->GetImageInfo().width; info.guest_address = VAddr(splash->GetImageData().data()); info.guest_size_bytes = splash->GetImageData().size(); - splash_img.emplace(instance, schedulers[SchedulerType::Present], info); + splash_img.emplace(instance, present_scheduler, info); texture_cache.RefreshImage(*splash_img); } frame = PrepareFrameInternal(*splash_img); @@ -186,7 +185,7 @@ Frame* RendererVulkan::PrepareFrameInternal(VideoCore::Image& image, bool is_eop // EOP flips are triggered from GPU thread to use the drawing scheduler to record // commands. Otherwise we are dealing with a CPU flip which could have arrived // from any guest thread. Use a separate scheduler for that. - auto& scheduler = schedulers[is_eop ? SchedulerType::Draw : SchedulerType::CpuFlip]; + auto& scheduler = is_eop ? draw_scheduler : flip_scheduler; const auto cmdbuf = scheduler.CommandBuffer(); image.Transit(vk::ImageLayout::eTransferSrcOptimal, vk::AccessFlagBits::eTransferRead, @@ -253,7 +252,7 @@ void RendererVulkan::Present(Frame* frame) { const vk::Image swapchain_image = swapchain.Image(); - auto& scheduler = schedulers[SchedulerType::Present]; + auto& scheduler = present_scheduler; const auto cmdbuf = scheduler.CommandBuffer(); { auto* profiler_ctx = instance.GetProfilerContext(); diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.h b/src/video_core/renderer_vulkan/renderer_vulkan.h index 0bff8e56e..3fe9267fe 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.h +++ b/src/video_core/renderer_vulkan/renderer_vulkan.h @@ -83,7 +83,9 @@ private: Frontend::WindowSDL& window; AmdGpu::Liverpool* liverpool; Instance instance; - std::array schedulers; + Scheduler draw_scheduler; + Scheduler present_scheduler; + Scheduler flip_scheduler; Swapchain swapchain; std::unique_ptr rasterizer; VideoCore::TextureCache texture_cache;