driver: Make flip blocking

This commit is contained in:
IndecisiveTurtle 2024-07-13 18:17:49 +03:00
parent 2e4f32a840
commit 502dc1cbf3
5 changed files with 20 additions and 20 deletions

View file

@ -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; });

View file

@ -12,6 +12,10 @@
extern std::unique_ptr<Vulkan::RendererVulkan> renderer;
extern std::unique_ptr<AmdGpu::Liverpool> 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();

View file

@ -362,11 +362,6 @@ Liverpool::Task Liverpool::ProcessGraphics(std::span<const u32> dcb, std::span<c
}
case PM4ItOpcode::EventWriteEop: {
const auto* event_eop = reinterpret_cast<const PM4CmdEventWriteEop*>(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<const u32> dcb, std::span<c
const u32 data_size = (header->type3.count.Value() - 2) * 4;
u64* address = write_data->Address<u64*>();
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();

View file

@ -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<Rasterizer>(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<Rasterizer>(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();

View file

@ -83,7 +83,9 @@ private:
Frontend::WindowSDL& window;
AmdGpu::Liverpool* liverpool;
Instance instance;
std::array<Scheduler, 3> schedulers;
Scheduler draw_scheduler;
Scheduler present_scheduler;
Scheduler flip_scheduler;
Swapchain swapchain;
std::unique_ptr<Rasterizer> rasterizer;
VideoCore::TextureCache texture_cache;