dolphin/Source/Core/VideoBackends/Vulkan/PresentWait.cpp

77 lines
1.6 KiB
C++

// Copyright 2023 Dolphin Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "VideoBackends/Vulkan/PresentWait.h"
#include <deque>
#include <thread>
#include <tuple>
#include "Common/WorkQueueThread.h"
#include "VideoBackends/Vulkan/VulkanContext.h"
#include "VideoBackends/Vulkan/VulkanLoader.h"
#include "VideoCommon/PerformanceMetrics.h"
namespace Vulkan
{
static VkDevice s_device;
struct Wait
{
u64 present_id;
VkSwapchainKHR swapchain;
};
static Common::WorkQueueThread<Wait> s_present_wait_thread;
void WaitFunction(Wait wait)
{
do
{
// We choose a timeout of 20ms so can poll for IsFlushing
VkResult res = vkWaitForPresentKHR(s_device, wait.swapchain, wait.present_id, 20'000'000);
if (res == VK_TIMEOUT)
{
WARN_LOG_FMT(VIDEO, "vkWaitForPresentKHR timed out, retrying {}", wait.present_id);
continue;
}
if (res != VK_SUCCESS)
{
LOG_VULKAN_ERROR(res, "vkWaitForPresentKHR failed: ");
}
if (res == VK_SUCCESS)
g_perf_metrics.CountPresent();
return;
} while (!s_present_wait_thread.IsCancelling());
}
void StartPresentWaitThread()
{
s_device = g_vulkan_context->GetDevice();
s_present_wait_thread.Reset("PresentWait", WaitFunction);
}
void StopPresentWaitThread()
{
s_present_wait_thread.Shutdown();
}
void PresentQueued(u64 present_id, VkSwapchainKHR swapchain)
{
s_present_wait_thread.EmplaceItem(Wait{present_id, swapchain});
}
void FlushPresentWaitQueue()
{
s_present_wait_thread.Cancel();
s_present_wait_thread.WaitForCompletion();
}
} // namespace Vulkan