add experimental flags for present mode and fps limit

This commit is contained in:
PancakeTAS 2025-07-18 00:22:10 +02:00
parent 1f8e3222d3
commit 6e86945dc8
No known key found for this signature in database
5 changed files with 51 additions and 7 deletions

View file

@ -1,10 +1,13 @@
#pragma once
#include <atomic>
#include <vulkan/vulkan_core.h>
#include <string_view>
#include <cstddef>
#include <vector>
#include <atomic>
#include <memory>
#include <string>
#include <string_view>
namespace Config {
@ -26,6 +29,11 @@ namespace Config {
/// Whether HDR is enabled
bool hdr{false};
/// Experimental flag for overriding the synchronization method.
VkPresentModeKHR e_present;
/// Experimental flag for limiting the framerate of DXVK games.
uint32_t e_fps_limit;
/// Atomic property to check if the configuration is valid or outdated.
std::shared_ptr<std::atomic_bool> valid;
};

View file

@ -1,6 +1,7 @@
#include "config/config.hpp"
#include "common/exception.hpp"
#include <vulkan/vulkan_core.h>
#include <linux/limits.h>
#include <sys/inotify.h>
#include <sys/poll.h>
@ -209,7 +210,7 @@ bool Config::updateConfig(const std::string& file) {
// parse global configuration
const toml::value globalTable = toml::find_or_default<toml::table>(toml, "global");
const Configuration global{
Configuration global{
.enable = toml::find_or(globalTable, "enable", false),
.dll = toml::find_or(globalTable, "dll", std::string()),
.env = parse_env(toml::find_or(globalTable, "env", std::string())),
@ -217,6 +218,10 @@ bool Config::updateConfig(const std::string& file) {
.flowScale = toml::find_or(globalTable, "flow_scale", 1.0F),
.performance = toml::find_or(globalTable, "performance_mode", false),
.hdr = toml::find_or(globalTable, "hdr_mode", false),
.e_present = into_present(
toml::find_or(globalTable, "experimental_present_mode", ""),
VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR),
.e_fps_limit = toml::find_or(globalTable, "experimental_fps_limit", 0U),
.valid = globalConf.valid // use the same validity flag
};
@ -249,6 +254,10 @@ bool Config::updateConfig(const std::string& file) {
.flowScale = toml::find_or(gameTable, "flow_scale", global.flowScale),
.performance = toml::find_or(gameTable, "performance_mode", global.performance),
.hdr = toml::find_or(gameTable, "hdr_mode", global.hdr),
.e_present = into_present(
toml::find_or(gameTable, "experimental_present_mode", ""),
global.e_present),
.e_fps_limit = toml::find_or(gameTable, "experimental_fps_limit", global.e_fps_limit),
.valid = global.valid // only need a single validity flag
};

View file

@ -51,6 +51,7 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain,
std::cerr << " Flow Scale: " << conf.flowScale << '\n';
std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n';
std::cerr << " HDR Mode: " << (conf.hdr ? "Enabled" : "Disabled") << '\n';
if (conf.e_present != 2) std::cerr << " ! Present Mode: " << conf.e_present << '\n';
}
// we could take the format from the swapchain,
// but honestly this is safer.

View file

@ -107,6 +107,7 @@ namespace {
std::unordered_map<VkSwapchainKHR, LsContext> swapchains;
std::unordered_map<VkSwapchainKHR, VkDevice> swapchainToDeviceTable;
std::unordered_map<VkSwapchainKHR, VkPresentModeKHR> swapchainToPresent;
///
/// Adjust swapchain creation parameters and create a swapchain context.
@ -148,8 +149,8 @@ namespace {
createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;
createInfo.imageUsage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
// enforce vsync
createInfo.presentMode = VK_PRESENT_MODE_FIFO_KHR;
// enforce present mode
createInfo.presentMode = Config::activeConf.e_present;
// retire potential old swapchain
if (pCreateInfo->oldSwapchain) {
@ -163,6 +164,8 @@ namespace {
return res; // can't be caused by lsfg-vk (yet)
try {
swapchainToPresent.emplace(*pSwapchain, createInfo.presentMode);
// get all swapchain images
uint32_t imageCount{};
res = Layer::ovkGetSwapchainImagesKHR(device, *pSwapchain, &imageCount, nullptr);
@ -228,7 +231,16 @@ namespace {
}
auto& swapchain = it3->second;
// enforce vsync | NOLINTBEGIN
// find present mode
auto it4 = swapchainToPresent.find(*pPresentInfo->pSwapchains);
if (it4 == swapchainToPresent.end()) {
Utils::logLimitN("swapMap", 5,
"Swapchain present mode not found in map");
return Layer::ovkQueuePresentKHR(queue, pPresentInfo);
}
auto& present = it4->second;
// enforce present mode | NOLINTBEGIN
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage"
const VkSwapchainPresentModeInfoEXT* presentModeInfo =
@ -237,7 +249,7 @@ namespace {
if (presentModeInfo->sType == VK_STRUCTURE_TYPE_SWAPCHAIN_PRESENT_MODE_INFO_EXT) {
for (size_t i = 0; i < presentModeInfo->swapchainCount; i++)
const_cast<VkPresentModeKHR*>(presentModeInfo->pPresentModes)[i] =
VK_PRESENT_MODE_FIFO_KHR;
present;
}
presentModeInfo =
reinterpret_cast<const VkSwapchainPresentModeInfoEXT*>(presentModeInfo->pNext);
@ -252,6 +264,10 @@ namespace {
if (!conf.valid->load(std::memory_order_relaxed))
return VK_ERROR_OUT_OF_DATE_KHR;
// ensure present mode is still valid
if (present != conf.e_present)
return VK_ERROR_OUT_OF_DATE_KHR;
// skip if disabled
if (!conf.enable)
return Layer::ovkQueuePresentKHR(queue, pPresentInfo);
@ -280,6 +296,7 @@ namespace {
const VkAllocationCallbacks* pAllocator) noexcept {
swapchains.erase(swapchain);
swapchainToDeviceTable.erase(swapchain);
swapchainToPresent.erase(swapchain);
Layer::ovkDestroySwapchainKHR(device, swapchain, pAllocator);
}
}

View file

@ -46,6 +46,15 @@ namespace {
std::cerr << " Flow Scale: " << conf.flowScale << '\n';
std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n';
std::cerr << " HDR Mode: " << (conf.hdr ? "Enabled" : "Disabled") << '\n';
if (conf.e_present != 2) std::cerr << " ! Present Mode: " << conf.e_present << '\n';
if (conf.e_fps_limit > 0) std::cerr << " ! FPS Limit: " << conf.e_fps_limit << '\n';
// update environment variables
unsetenv("MESA_VK_WSI_PRESENT_MODE"); // NOLINT
for (const auto& [key, value] : conf.env)
setenv(key.c_str(), value.c_str(), 1); // NOLINT
if (conf.e_fps_limit > 0)
setenv("DXVK_FRAME_RATE", std::to_string(conf.e_fps_limit).c_str(), 1); // NOLINT
// load shaders
try {