vk_present_manager: Add toggle for async presentation

This commit is contained in:
GPUCode 2023-05-01 23:12:28 +03:00
parent 1d7abac84b
commit f403d27941
10 changed files with 45 additions and 6 deletions

View file

@ -205,6 +205,7 @@ void RestoreGlobalState(bool is_powered_on) {
// Renderer // Renderer
values.fsr_sharpening_slider.SetGlobal(true); values.fsr_sharpening_slider.SetGlobal(true);
values.renderer_backend.SetGlobal(true); values.renderer_backend.SetGlobal(true);
values.async_presentation.SetGlobal(true);
values.renderer_force_max_clock.SetGlobal(true); values.renderer_force_max_clock.SetGlobal(true);
values.vulkan_device.SetGlobal(true); values.vulkan_device.SetGlobal(true);
values.fullscreen_mode.SetGlobal(true); values.fullscreen_mode.SetGlobal(true);

View file

@ -422,6 +422,7 @@ struct Values {
// Renderer // Renderer
SwitchableSetting<RendererBackend, true> renderer_backend{ SwitchableSetting<RendererBackend, true> renderer_backend{
RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"}; RendererBackend::Vulkan, RendererBackend::OpenGL, RendererBackend::Null, "backend"};
SwitchableSetting<bool> async_presentation{false, "async_presentation"};
SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"}; SwitchableSetting<bool> renderer_force_max_clock{false, "force_max_clock"};
Setting<bool> renderer_debug{false, "debug"}; Setting<bool> renderer_debug{false, "debug"};
Setting<bool> renderer_shader_feedback{false, "shader_feedback"}; Setting<bool> renderer_shader_feedback{false, "shader_feedback"};

View file

@ -2,6 +2,7 @@
// SPDX-License-Identifier: GPL-2.0-or-later // SPDX-License-Identifier: GPL-2.0-or-later
#include "common/microprofile.h" #include "common/microprofile.h"
#include "common/settings.h"
#include "common/thread.h" #include "common/thread.h"
#include "video_core/renderer_vulkan/vk_present_manager.h" #include "video_core/renderer_vulkan/vk_present_manager.h"
#include "video_core/renderer_vulkan/vk_scheduler.h" #include "video_core/renderer_vulkan/vk_scheduler.h"
@ -97,6 +98,7 @@ PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const
: render_window{render_window_}, device{device_}, : render_window{render_window_}, device{device_},
memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_}, memory_allocator{memory_allocator_}, scheduler{scheduler_}, swapchain{swapchain_},
blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())}, blit_supported{CanBlitToSwapchain(device.GetPhysical(), swapchain.GetImageViewFormat())},
use_present_thread{Settings::values.async_presentation.GetValue()},
image_count{swapchain.GetImageCount()} { image_count{swapchain.GetImageCount()} {
auto& dld = device.GetLogical(); auto& dld = device.GetLogical();
@ -126,7 +128,9 @@ PresentManager::PresentManager(Core::Frontend::EmuWindow& render_window_, const
free_queue.push(&frame); free_queue.push(&frame);
} }
if (use_present_thread) {
present_thread = std::jthread([this](std::stop_token token) { PresentThread(token); }); present_thread = std::jthread([this](std::stop_token token) { PresentThread(token); });
}
} }
PresentManager::~PresentManager() = default; PresentManager::~PresentManager() = default;
@ -150,6 +154,12 @@ Frame* PresentManager::GetRenderFrame() {
} }
void PresentManager::PushFrame(Frame* frame) { void PresentManager::PushFrame(Frame* frame) {
if (!use_present_thread) {
CopyToSwapchain(frame);
free_queue.push(frame);
return;
}
std::unique_lock lock{queue_mutex}; std::unique_lock lock{queue_mutex};
present_queue.push(frame); present_queue.push(frame);
frame_cv.notify_one(); frame_cv.notify_one();
@ -227,6 +237,10 @@ void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_
} }
void PresentManager::WaitPresent() { void PresentManager::WaitPresent() {
if (!use_present_thread) {
return;
}
// Wait for the present queue to be empty // Wait for the present queue to be empty
{ {
std::unique_lock queue_lock{queue_mutex}; std::unique_lock queue_lock{queue_mutex};

View file

@ -75,7 +75,8 @@ private:
std::mutex queue_mutex; std::mutex queue_mutex;
std::mutex free_mutex; std::mutex free_mutex;
std::jthread present_thread; std::jthread present_thread;
bool blit_supported{}; bool blit_supported;
bool use_present_thread;
std::size_t image_count; std::size_t image_count;
}; };

View file

@ -692,6 +692,7 @@ void Config::ReadRendererValues() {
qt_config->beginGroup(QStringLiteral("Renderer")); qt_config->beginGroup(QStringLiteral("Renderer"));
ReadGlobalSetting(Settings::values.renderer_backend); ReadGlobalSetting(Settings::values.renderer_backend);
ReadGlobalSetting(Settings::values.async_presentation);
ReadGlobalSetting(Settings::values.renderer_force_max_clock); ReadGlobalSetting(Settings::values.renderer_force_max_clock);
ReadGlobalSetting(Settings::values.vulkan_device); ReadGlobalSetting(Settings::values.vulkan_device);
ReadGlobalSetting(Settings::values.fullscreen_mode); ReadGlobalSetting(Settings::values.fullscreen_mode);
@ -1313,6 +1314,7 @@ void Config::SaveRendererValues() {
static_cast<u32>(Settings::values.renderer_backend.GetValue(global)), static_cast<u32>(Settings::values.renderer_backend.GetValue(global)),
static_cast<u32>(Settings::values.renderer_backend.GetDefault()), static_cast<u32>(Settings::values.renderer_backend.GetDefault()),
Settings::values.renderer_backend.UsingGlobal()); Settings::values.renderer_backend.UsingGlobal());
WriteGlobalSetting(Settings::values.async_presentation);
WriteGlobalSetting(Settings::values.renderer_force_max_clock); WriteGlobalSetting(Settings::values.renderer_force_max_clock);
WriteGlobalSetting(Settings::values.vulkan_device); WriteGlobalSetting(Settings::values.vulkan_device);
WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()), WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()),

View file

@ -22,11 +22,13 @@ ConfigureGraphicsAdvanced::~ConfigureGraphicsAdvanced() = default;
void ConfigureGraphicsAdvanced::SetConfiguration() { void ConfigureGraphicsAdvanced::SetConfiguration() {
const bool runtime_lock = !system.IsPoweredOn(); const bool runtime_lock = !system.IsPoweredOn();
ui->use_vsync->setEnabled(runtime_lock); ui->use_vsync->setEnabled(runtime_lock);
ui->async_present->setEnabled(runtime_lock);
ui->renderer_force_max_clock->setEnabled(runtime_lock); ui->renderer_force_max_clock->setEnabled(runtime_lock);
ui->async_astc->setEnabled(runtime_lock); ui->async_astc->setEnabled(runtime_lock);
ui->use_asynchronous_shaders->setEnabled(runtime_lock); ui->use_asynchronous_shaders->setEnabled(runtime_lock);
ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); ui->anisotropic_filtering_combobox->setEnabled(runtime_lock);
ui->async_present->setChecked(Settings::values.async_presentation.GetValue());
ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue()); ui->renderer_force_max_clock->setChecked(Settings::values.renderer_force_max_clock.GetValue());
ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue());
ui->async_astc->setChecked(Settings::values.async_astc.GetValue()); ui->async_astc->setChecked(Settings::values.async_astc.GetValue());
@ -54,6 +56,8 @@ void ConfigureGraphicsAdvanced::SetConfiguration() {
void ConfigureGraphicsAdvanced::ApplyConfiguration() { void ConfigureGraphicsAdvanced::ApplyConfiguration() {
ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy); ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.async_presentation,
ui->async_present, async_present);
ConfigurationShared::ApplyPerGameSetting(&Settings::values.renderer_force_max_clock, ConfigurationShared::ApplyPerGameSetting(&Settings::values.renderer_force_max_clock,
ui->renderer_force_max_clock, ui->renderer_force_max_clock,
renderer_force_max_clock); renderer_force_max_clock);
@ -90,6 +94,7 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
// Disable if not global (only happens during game) // Disable if not global (only happens during game)
if (Settings::IsConfiguringGlobal()) { if (Settings::IsConfiguringGlobal()) {
ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal());
ui->async_present->setEnabled(Settings::values.async_presentation.UsingGlobal());
ui->renderer_force_max_clock->setEnabled( ui->renderer_force_max_clock->setEnabled(
Settings::values.renderer_force_max_clock.UsingGlobal()); Settings::values.renderer_force_max_clock.UsingGlobal());
ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal());
@ -107,6 +112,8 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() {
return; return;
} }
ConfigurationShared::SetColoredTristate(ui->async_present, Settings::values.async_presentation,
async_present);
ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock, ConfigurationShared::SetColoredTristate(ui->renderer_force_max_clock,
Settings::values.renderer_force_max_clock, Settings::values.renderer_force_max_clock,
renderer_force_max_clock); renderer_force_max_clock);

View file

@ -36,6 +36,7 @@ private:
std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui;
ConfigurationShared::CheckState async_present;
ConfigurationShared::CheckState renderer_force_max_clock; ConfigurationShared::CheckState renderer_force_max_clock;
ConfigurationShared::CheckState use_vsync; ConfigurationShared::CheckState use_vsync;
ConfigurationShared::CheckState async_astc; ConfigurationShared::CheckState async_astc;

View file

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>404</width> <width>404</width>
<height>321</height> <height>376</height>
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
@ -69,6 +69,13 @@
</layout> </layout>
</widget> </widget>
</item> </item>
<item>
<widget class="QCheckBox" name="async_present">
<property name="text">
<string>Enable asynchronous presentation (Vulkan only)</string>
</property>
</widget>
</item>
<item> <item>
<widget class="QCheckBox" name="renderer_force_max_clock"> <widget class="QCheckBox" name="renderer_force_max_clock">
<property name="toolTip"> <property name="toolTip">

View file

@ -300,6 +300,7 @@ void Config::ReadValues() {
// Renderer // Renderer
ReadSetting("Renderer", Settings::values.renderer_backend); ReadSetting("Renderer", Settings::values.renderer_backend);
ReadSetting("Renderer", Settings::values.async_presentation);
ReadSetting("Renderer", Settings::values.renderer_force_max_clock); ReadSetting("Renderer", Settings::values.renderer_force_max_clock);
ReadSetting("Renderer", Settings::values.renderer_debug); ReadSetting("Renderer", Settings::values.renderer_debug);
ReadSetting("Renderer", Settings::values.renderer_shader_feedback); ReadSetting("Renderer", Settings::values.renderer_shader_feedback);

View file

@ -264,6 +264,10 @@ cpuopt_unsafe_ignore_global_monitor =
# 0: OpenGL, 1 (default): Vulkan # 0: OpenGL, 1 (default): Vulkan
backend = backend =
# Whether to enable asynchronous presentation (Vulkan only)
# 0 (default): Off, 1: On
async_presentation =
# Enable graphics API debugging mode. # Enable graphics API debugging mode.
# 0 (default): Disabled, 1: Enabled # 0 (default): Disabled, 1: Enabled
debug = debug =