From 62eaead3a3293d55b6434908c9e292cb4dabd6cc Mon Sep 17 00:00:00 2001 From: nmzik Date: Sat, 29 Aug 2026 01:26:31 +0400 Subject: [PATCH] add configurable Vulkan present modes Co-authored-by: Techx3 <56268269+Techx3@users.noreply.github.com> --- CMakeLists.txt | 5 ++ src/common/emulatorConfig.cpp | 4 ++ src/common/emulatorConfig.h | 4 ++ .../presentation/window/swapchain.cpp | 17 ++++++- .../forms/configuration_edit_dialog.ui | 48 ++++++++++++------- src/launcher/include/configuration.h | 10 ++++ src/launcher/src/configurationEditDialog.cpp | 3 ++ src/launcher/src/mainDialog.cpp | 1 + src/main.cpp | 6 +++ 9 files changed, 80 insertions(+), 18 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index de7089a1..1347d463 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -529,6 +529,11 @@ if(BUILD_TESTING) add_test(NAME emulator_user_name_too_long COMMAND $ --help --user-name 12345678901234567) set_tests_properties(emulator_user_name_too_long PROPERTIES WILL_FAIL TRUE) + add_test(NAME emulator_present_mode_cli + COMMAND $ --help --present-mode Immediate) + add_test(NAME emulator_present_mode_invalid + COMMAND $ --help --present-mode Invalid) + set_tests_properties(emulator_present_mode_invalid PROPERTIES WILL_FAIL TRUE) add_test(NAME ime_dialog COMMAND $) add_test(NAME shader_cfg COMMAND $) add_test(NAME scalar_provenance COMMAND $) diff --git a/src/common/emulatorConfig.cpp b/src/common/emulatorConfig.cpp index 290bf9cc..5f3995e4 100644 --- a/src/common/emulatorConfig.cpp +++ b/src/common/emulatorConfig.cpp @@ -38,6 +38,10 @@ const std::string& GetUserName() { return g_config->user_name; } +PresentMode GetPresentMode() { + return g_config->present_mode; +} + bool FullscreenEnabled() { return g_config->fullscreen_enabled; } diff --git a/src/common/emulatorConfig.h b/src/common/emulatorConfig.h index 7de12efc..8586a5ee 100644 --- a/src/common/emulatorConfig.h +++ b/src/common/emulatorConfig.h @@ -27,6 +27,8 @@ enum class ProfilerDirection { None, Network }; enum class OutputDirection { Silent, Console, File }; +enum class PresentMode { Fifo, Mailbox, Immediate }; + using Keymap = std::vector; constexpr uint32_t DEFAULT_CONSOLE_LANGUAGE = 1; @@ -37,6 +39,7 @@ struct ConfigOptions { uint32_t screen_width = 1280; uint32_t screen_height = 720; std::string user_name = "Kyty"; + PresentMode present_mode = PresentMode::Fifo; bool fullscreen_enabled = false; uint32_t vblank_frequency = 60; uint32_t console_language = DEFAULT_CONSOLE_LANGUAGE; @@ -67,6 +70,7 @@ void Load(const ConfigOptions& cfg); uint32_t GetScreenWidth(); uint32_t GetScreenHeight(); const std::string& GetUserName(); +PresentMode GetPresentMode(); bool FullscreenEnabled(); uint32_t GetVblankFrequency(); uint32_t GetConsoleLanguage(); diff --git a/src/graphics/presentation/window/swapchain.cpp b/src/graphics/presentation/window/swapchain.cpp index 1a964730..cfb6a277 100644 --- a/src/graphics/presentation/window/swapchain.cpp +++ b/src/graphics/presentation/window/swapchain.cpp @@ -1,5 +1,6 @@ #include "common/assert.h" #include "common/common.h" +#include "common/emulatorConfig.h" #include "common/logging/log.h" #include "common/profiler.h" #include "common/threads.h" @@ -428,7 +429,21 @@ void Swapchain::Create() { create_info.imageSharingMode = vk::SharingMode::eExclusive; create_info.preTransform = transform; create_info.compositeAlpha = composite; - create_info.presentMode = vk::PresentModeKHR::eFifo; + switch (Config::GetPresentMode()) { + case Config::PresentMode::Mailbox: + create_info.presentMode = vk::PresentModeKHR::eMailbox; + break; + case Config::PresentMode::Immediate: + create_info.presentMode = vk::PresentModeKHR::eImmediate; + break; + case Config::PresentMode::Fifo: + default: create_info.presentMode = vk::PresentModeKHR::eFifo; break; + } + if (std::find(surface.present_modes.begin(), surface.present_modes.end(), + create_info.presentMode) == surface.present_modes.end()) { + LOGF("warning: requested present mode is unavailable; falling back to Fifo\n"); + create_info.presentMode = vk::PresentModeKHR::eFifo; + } create_info.clipped = VK_TRUE; RequireVulkanSuccess(graphics.device.createSwapchainKHR(&create_info, nullptr, &m_handle), "vkCreateSwapchainKHR"); diff --git a/src/launcher/forms/configuration_edit_dialog.ui b/src/launcher/forms/configuration_edit_dialog.ui index 27ab6f18..fc464417 100644 --- a/src/launcher/forms/configuration_edit_dialog.ui +++ b/src/launcher/forms/configuration_edit_dialog.ui @@ -133,13 +133,27 @@ + + + Present mode: + + + + + + + Vulkan swapchain presentation mode + + + + Vblank frequency: - + Virtual display refresh rate used for frame pacing @@ -155,56 +169,56 @@ - + Console language: - + Language - + Shader optimization type: - + Optimize shaders for code size or performance - + Shader log direction: - + Dump shaders to file or console window. If enabled may decrease emulator performance - + Shader log folder: - + Specify directory to dump shaders @@ -214,14 +228,14 @@ - + Command buffer dump folder: - + Specify directory to dump command buffers @@ -231,28 +245,28 @@ - + Printf direction: - + Print logs to file or console window. If enabled may decrease emulator performance - + Printf output file: - + Specify file to dump logs @@ -262,14 +276,14 @@ - + Profiler direction: - + Enable or disable profiler. If enabled may decrease emulator performance diff --git a/src/launcher/include/configuration.h b/src/launcher/include/configuration.h index fe6e3ced..b656f3e3 100644 --- a/src/launcher/include/configuration.h +++ b/src/launcher/include/configuration.h @@ -62,6 +62,9 @@ public: enum class ShaderOptimizationType { None, Size, Performance }; Q_ENUM(ShaderOptimizationType) + enum class PresentMode { Fifo, Mailbox, Immediate }; + Q_ENUM(PresentMode) + enum class ShaderLogDirection { Silent, Console, File }; Q_ENUM(ShaderLogDirection) @@ -88,6 +91,7 @@ public: Resolution screen_resolution = Resolution::R1280X720; QString user_name = "Kyty"; + PresentMode present_mode = PresentMode::Fifo; bool fullscreen_enabled = false; int vblank_frequency = 60; int console_language = DEFAULT_CONSOLE_LANGUAGE; @@ -112,6 +116,7 @@ public: void CopyEmulatorSettingsFrom(const Configuration& other) { screen_resolution = other.screen_resolution; user_name = other.user_name; + present_mode = other.present_mode; fullscreen_enabled = other.fullscreen_enabled; vblank_frequency = other.vblank_frequency; console_language = other.console_language; @@ -153,6 +158,7 @@ public: KYTY_CFG_SET(custom_settings); KYTY_CFG_SET(screen_resolution); KYTY_CFG_SET(user_name); + KYTY_CFG_SET(present_mode); KYTY_CFG_SET(fullscreen_enabled); KYTY_CFG_SET(vblank_frequency); KYTY_CFG_SET(console_language); @@ -181,6 +187,10 @@ public: KYTY_CFG_GET(custom_settings); KYTY_CFG_GET(screen_resolution); user_name = s->value("user_name", user_name).toString(); + KYTY_CFG_GET(present_mode); + if (EnumToText(present_mode).isEmpty()) { + present_mode = PresentMode::Fifo; + } KYTY_CFG_GET(fullscreen_enabled); vblank_frequency = s->value("vblank_frequency", vblank_frequency).toInt(); console_language = s->value("console_language", console_language).toInt(); diff --git a/src/launcher/src/configurationEditDialog.cpp b/src/launcher/src/configurationEditDialog.cpp index bc12d57e..80b8d1ac 100644 --- a/src/launcher/src/configurationEditDialog.cpp +++ b/src/launcher/src/configurationEditDialog.cpp @@ -157,6 +157,7 @@ void ConfigurationEditDialog::Init(const Configuration& info) { m_ui->lineEdit_user_name->setMaxLength(static_cast(Config::MAX_USER_NAME_LENGTH)); m_ui->lineEdit_user_name->setText(info.user_name); ListInit(m_ui->comboBox_screen_resolution, info.screen_resolution); + ListInit(m_ui->comboBox_present_mode, info.present_mode); m_ui->checkBox_fullscreen->setChecked(info.fullscreen_enabled); m_ui->spinBox_vblank_frequency->setValue(info.vblank_frequency); m_ui->comboBox_console_language->clear(); @@ -290,6 +291,8 @@ static void UpdateInfo(Configuration& info, Ui::ConfigurationEditDialog& ui) { info.user_name = ui.lineEdit_user_name->text().trimmed(); info.screen_resolution = TextToEnum(ui.comboBox_screen_resolution->currentText()); + info.present_mode = + TextToEnum(ui.comboBox_present_mode->currentText()); info.fullscreen_enabled = ui.checkBox_fullscreen->isChecked(); info.vblank_frequency = ui.spinBox_vblank_frequency->value(); info.console_language = ui.comboBox_console_language->currentIndex(); diff --git a/src/launcher/src/mainDialog.cpp b/src/launcher/src/mainDialog.cpp index 245fb95c..180ab133 100644 --- a/src/launcher/src/mainDialog.cpp +++ b/src/launcher/src/mainDialog.cpp @@ -205,6 +205,7 @@ static QStringList CreateEmulatorArgs(const Configuration& info) { args << "--screen-width" << r.at(0); args << "--screen-height" << r.at(1); args << "--user-name" << info.user_name; + args << "--present-mode" << EnumToText(info.present_mode); if (info.fullscreen_enabled) { args << "--fullscreen"; } diff --git a/src/main.cpp b/src/main.cpp index afff146b..6983f8c3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -49,6 +49,7 @@ static void PrintUsage() { ::printf(" --screen-height Window height. Default: 720.\n"); ::printf( " --user-name Local user name (1-16 bytes). Default: Kyty.\n"); + ::printf(" --present-mode Fifo, Mailbox, or Immediate. Default: Fifo.\n"); ::printf(" --fullscreen Run in borderless desktop fullscreen.\n"); ::printf(" --vblank-frequency Virtual vblank frequency. Default: 60.\n"); ::printf(" --console-language <0-29> Console language. Default: 1 (English US).\n"); @@ -210,6 +211,11 @@ static bool ParseArgs(int argc, char* argv[], RunOptions& options, bool& show_he return false; } options.config.user_name = value; + } else if (arg == "--present-mode") { + if (!ParseEnum(value, options.config.present_mode)) { + ::printf("invalid present mode: %s\n", value.c_str()); + return false; + } } else if (arg == "--vblank-frequency") { const int32_t vblank_frequency = Common::ToInt32(value); options.config.vblank_frequency =