add experimental flags for present mode and fps limit

This commit is contained in:
PancakeTAS 2025-07-18 00:22:10 +02:00 committed by Pancake
parent ab867ff272
commit 8b29b952fd
5 changed files with 51 additions and 7 deletions

View file

@ -1,10 +1,13 @@
#pragma once #pragma once
#include <atomic> #include <vulkan/vulkan_core.h>
#include <string_view>
#include <cstddef> #include <cstddef>
#include <vector>
#include <atomic>
#include <memory> #include <memory>
#include <string> #include <string>
#include <string_view>
namespace Config { namespace Config {
@ -26,6 +29,11 @@ namespace Config {
/// Whether HDR is enabled /// Whether HDR is enabled
bool hdr{false}; 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. /// Atomic property to check if the configuration is valid or outdated.
std::shared_ptr<std::atomic_bool> valid; std::shared_ptr<std::atomic_bool> valid;
}; };

View file

@ -1,6 +1,7 @@
#include "config/config.hpp" #include "config/config.hpp"
#include "common/exception.hpp" #include "common/exception.hpp"
#include <vulkan/vulkan_core.h>
#include <linux/limits.h> #include <linux/limits.h>
#include <sys/inotify.h> #include <sys/inotify.h>
#include <sys/poll.h> #include <sys/poll.h>
@ -209,7 +210,7 @@ bool Config::updateConfig(const std::string& file) {
// parse global configuration // parse global configuration
const toml::value globalTable = toml::find_or_default<toml::table>(toml, "global"); const toml::value globalTable = toml::find_or_default<toml::table>(toml, "global");
const Configuration global{ Configuration global{
.enable = toml::find_or(globalTable, "enable", false), .enable = toml::find_or(globalTable, "enable", false),
.dll = toml::find_or(globalTable, "dll", std::string()), .dll = toml::find_or(globalTable, "dll", std::string()),
.env = parse_env(toml::find_or(globalTable, "env", 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), .flowScale = toml::find_or(globalTable, "flow_scale", 1.0F),
.performance = toml::find_or(globalTable, "performance_mode", false), .performance = toml::find_or(globalTable, "performance_mode", false),
.hdr = toml::find_or(globalTable, "hdr_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 .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), .flowScale = toml::find_or(gameTable, "flow_scale", global.flowScale),
.performance = toml::find_or(gameTable, "performance_mode", global.performance), .performance = toml::find_or(gameTable, "performance_mode", global.performance),
.hdr = toml::find_or(gameTable, "hdr_mode", global.hdr), .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 .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 << " Flow Scale: " << conf.flowScale << '\n';
std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n'; std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n';
std::cerr << " HDR Mode: " << (conf.hdr ? "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, // we could take the format from the swapchain,
// but honestly this is safer. // but honestly this is safer.

View file

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

View file

@ -46,6 +46,15 @@ namespace {
std::cerr << " Flow Scale: " << conf.flowScale << '\n'; std::cerr << " Flow Scale: " << conf.flowScale << '\n';
std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n'; std::cerr << " Performance Mode: " << (conf.performance ? "Enabled" : "Disabled") << '\n';
std::cerr << " HDR Mode: " << (conf.hdr ? "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 // load shaders
try { try {