mirror of
https://github.com/PancakeTAS/lsfg-vk.git
synced 2026-04-25 20:02:13 +00:00
do not multithread
This commit is contained in:
parent
8b63447d41
commit
c1413a3ed9
5 changed files with 30 additions and 134 deletions
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <filesystem>
|
||||
#include <chrono>
|
||||
#include <cstddef>
|
||||
#include <vector>
|
||||
#include <atomic>
|
||||
|
|
@ -33,24 +35,17 @@ namespace Config {
|
|||
/// 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;
|
||||
/// Path to the configuration file.
|
||||
std::filesystem::path config_file;
|
||||
/// File timestamp of the configuration file
|
||||
std::chrono::time_point<std::chrono::file_clock> timestamp;
|
||||
};
|
||||
|
||||
/// Active configuration. Must be set in main.cpp.
|
||||
extern Configuration activeConf;
|
||||
|
||||
///
|
||||
/// Load the config file and create a file watcher.
|
||||
///
|
||||
/// @param file The path to the configuration file.
|
||||
///
|
||||
/// @throws std::runtime_error if an error occurs while loading the configuration file.
|
||||
///
|
||||
void loadAndWatchConfig(const std::string& file);
|
||||
|
||||
///
|
||||
/// Reread the configuration file while preserving the old configuration
|
||||
/// Read the configuration file while preserving the previous configuration
|
||||
/// in case of an error.
|
||||
///
|
||||
/// @param file The path to the configuration file.
|
||||
|
|
|
|||
|
|
@ -4,14 +4,9 @@
|
|||
#include "config/default_conf.hpp"
|
||||
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#include <linux/limits.h>
|
||||
#include <sys/inotify.h>
|
||||
#include <sys/poll.h>
|
||||
#include <toml11/find.hpp>
|
||||
#include <toml11/parser.hpp>
|
||||
#include <toml.hpp>
|
||||
#include <unistd.h>
|
||||
#include <poll.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <filesystem>
|
||||
|
|
@ -21,19 +16,11 @@
|
|||
#include <iostream>
|
||||
#include <optional>
|
||||
#include <fstream>
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <thread>
|
||||
#include <cerrno>
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <array>
|
||||
|
||||
using namespace Config;
|
||||
|
||||
|
|
@ -44,103 +31,6 @@ namespace {
|
|||
|
||||
Configuration Config::activeConf{};
|
||||
|
||||
namespace {
|
||||
[[noreturn]] void thread(
|
||||
const std::string& file,
|
||||
const std::shared_ptr<std::atomic_bool>& valid) {
|
||||
const int fd = inotify_init();
|
||||
if (fd < 0)
|
||||
throw std::runtime_error("Failed to initialize inotify:\n"
|
||||
"- " + std::string(strerror(errno)));
|
||||
|
||||
const std::string parent = std::filesystem::path(file).parent_path().string();
|
||||
const int wd = inotify_add_watch(fd, parent.c_str(),
|
||||
IN_MODIFY | IN_CLOSE_WRITE | IN_MOVE_SELF);
|
||||
if (wd < 0) {
|
||||
close(fd);
|
||||
|
||||
throw std::runtime_error("Failed to add inotify watch for " + parent + ":\n"
|
||||
"- " + std::string(strerror(errno)));
|
||||
}
|
||||
|
||||
// watch for changes
|
||||
std::optional<std::chrono::steady_clock::time_point> discard_until;
|
||||
const std::string filename = std::filesystem::path(file).filename().string();
|
||||
|
||||
std::array<char, (sizeof(inotify_event) + NAME_MAX + 1) * 20> buffer{};
|
||||
while (true) {
|
||||
// poll fd
|
||||
struct pollfd pfd{};
|
||||
pfd.fd = fd;
|
||||
pfd.events = POLLIN;
|
||||
const int pollRes = poll(&pfd, 1, 100);
|
||||
if (pollRes < 0 && errno != EINTR) {
|
||||
inotify_rm_watch(fd, wd);
|
||||
close(fd);
|
||||
|
||||
throw std::runtime_error("Error polling inotify events:\n"
|
||||
"- " + std::string(strerror(errno)));
|
||||
}
|
||||
|
||||
// read fd if there are events
|
||||
const ssize_t len = pollRes == 0 ? 0 : read(fd, buffer.data(), buffer.size());
|
||||
if (len <= 0 && errno != EINTR && pollRes > 0) {
|
||||
inotify_rm_watch(fd, wd);
|
||||
close(fd);
|
||||
|
||||
throw std::runtime_error("Error reading inotify events:\n"
|
||||
"- " + std::string(strerror(errno)));
|
||||
}
|
||||
|
||||
size_t i{};
|
||||
while (std::cmp_less(i, len)) {
|
||||
auto* event = reinterpret_cast<inotify_event*>(&buffer.at(i));
|
||||
i += sizeof(inotify_event) + event->len;
|
||||
if (event->len <= 0 || event->mask & IN_IGNORED)
|
||||
continue;
|
||||
|
||||
const std::string name(reinterpret_cast<char*>(event->name));
|
||||
if (name != filename)
|
||||
continue;
|
||||
|
||||
// stall a bit, then mark as invalid
|
||||
discard_until.emplace(std::chrono::steady_clock::now()
|
||||
+ std::chrono::milliseconds(500));
|
||||
}
|
||||
|
||||
auto now = std::chrono::steady_clock::now();
|
||||
if (discard_until.has_value() && now > *discard_until) {
|
||||
discard_until.reset();
|
||||
|
||||
// mark config as invalid
|
||||
valid->store(false, std::memory_order_release);
|
||||
|
||||
// and wait until it has been marked as valid again
|
||||
while (!valid->load(std::memory_order_acquire))
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Config::loadAndWatchConfig(const std::string& file) {
|
||||
globalConf.valid = std::make_shared<std::atomic_bool>(true);
|
||||
updateConfig(file);
|
||||
|
||||
// prepare config watcher
|
||||
if (std::getenv("LSFG_NO_HOT_RELOAD"))
|
||||
return;
|
||||
|
||||
std::thread([file = file, valid = globalConf.valid]() {
|
||||
try {
|
||||
thread(file, valid);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "lsfg-vk: Error in config watcher thread:\n";
|
||||
std::cerr << "- " << e.what() << '\n';
|
||||
}
|
||||
}).detach();
|
||||
}
|
||||
|
||||
namespace {
|
||||
/// Turn a string into a VkPresentModeKHR enum value.
|
||||
VkPresentModeKHR into_present(const std::string& mode) {
|
||||
|
|
@ -195,7 +85,6 @@ namespace {
|
|||
}
|
||||
|
||||
void Config::updateConfig(const std::string& file) {
|
||||
globalConf.valid->store(true, std::memory_order_relaxed);
|
||||
if (!std::filesystem::exists(file)) {
|
||||
std::cerr << "lsfg-vk: Placing default configuration file at " << file << '\n';
|
||||
const auto parent = std::filesystem::path(file).parent_path();
|
||||
|
|
@ -227,7 +116,8 @@ void Config::updateConfig(const std::string& file) {
|
|||
const toml::value globalTable = toml::find_or_default<toml::table>(toml, "global");
|
||||
const Configuration global{
|
||||
.dll = toml::find_or(globalTable, "dll", std::string()),
|
||||
.valid = globalConf.valid // use the same validity flag
|
||||
.config_file = file,
|
||||
.timestamp = std::filesystem::last_write_time(file)
|
||||
};
|
||||
|
||||
// validate global configuration
|
||||
|
|
@ -256,7 +146,8 @@ void Config::updateConfig(const std::string& file) {
|
|||
.hdr = toml::find_or(gameTable, "hdr_mode", false),
|
||||
.e_present = into_present(toml::find_or(gameTable, "experimental_present_mode", "")),
|
||||
.e_fps_limit = toml::find_or(gameTable, "experimental_fps_limit", 0U),
|
||||
.valid = global.valid // only need a single validity flag
|
||||
.config_file = file,
|
||||
.timestamp = global.timestamp
|
||||
};
|
||||
|
||||
// validate the configuration
|
||||
|
|
@ -279,8 +170,7 @@ Configuration Config::getConfig(const std::pair<std::string, std::string>& name)
|
|||
.enable = true,
|
||||
.multiplier = 2,
|
||||
.flowScale = 1.0F,
|
||||
.e_present = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR,
|
||||
.valid = std::make_shared<std::atomic_bool>(true)
|
||||
.e_present = VkPresentModeKHR::VK_PRESENT_MODE_FIFO_KHR
|
||||
};
|
||||
|
||||
const char* dll = std::getenv("LSFG_DLL_PATH");
|
||||
|
|
|
|||
|
|
@ -11,14 +11,16 @@
|
|||
#include <lsfg_3_1.hpp>
|
||||
#include <lsfg_3_1p.hpp>
|
||||
|
||||
#include <filesystem>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <chrono>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <thread>
|
||||
#include <array>
|
||||
|
||||
LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain,
|
||||
|
|
@ -27,8 +29,13 @@ LsContext::LsContext(const Hooks::DeviceInfo& info, VkSwapchainKHR swapchain,
|
|||
extent(extent) {
|
||||
// get updated configuration
|
||||
auto& conf = Config::activeConf;
|
||||
if (!conf.valid->load(std::memory_order_relaxed)) {
|
||||
if (!conf.config_file.empty()
|
||||
&& (
|
||||
!std::filesystem::exists(conf.config_file)
|
||||
|| conf.timestamp != std::filesystem::last_write_time(conf.config_file)
|
||||
)) {
|
||||
std::cerr << "lsfg-vk: Rereading configuration, as it is no longer valid.\n";
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(100));
|
||||
|
||||
// reread configuration
|
||||
const std::string file = Utils::getConfigFile();
|
||||
|
|
|
|||
|
|
@ -8,13 +8,13 @@
|
|||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include <unordered_map>
|
||||
#include <filesystem>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <atomic>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
|
@ -261,7 +261,11 @@ namespace {
|
|||
try {
|
||||
// ensure config is valid
|
||||
auto& conf = Config::activeConf;
|
||||
if (!conf.valid->load(std::memory_order_relaxed)) {
|
||||
if (!conf.config_file.empty()
|
||||
&& (
|
||||
!std::filesystem::exists(conf.config_file)
|
||||
|| conf.timestamp != std::filesystem::last_write_time(conf.config_file)
|
||||
)) {
|
||||
Layer::ovkQueuePresentKHR(queue, pPresentInfo);
|
||||
return VK_ERROR_OUT_OF_DATE_KHR;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ namespace {
|
|||
// read configuration
|
||||
const std::string file = Utils::getConfigFile();
|
||||
try {
|
||||
Config::loadAndWatchConfig(file);
|
||||
Config::updateConfig(file);
|
||||
} catch (const std::exception& e) {
|
||||
std::cerr << "lsfg-vk: An error occured while trying to parse the configuration, IGNORING:\n";
|
||||
std::cerr << "- " << e.what() << '\n';
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue