From 0923b4802a4fb64c052c5103d38e1dc005ab8370 Mon Sep 17 00:00:00 2001 From: PancakeTAS Date: Mon, 15 Dec 2025 20:37:46 +0100 Subject: [PATCH] refactor(cleanup): global cleanup --- .../VkLayer_LS_frame_generation.json | 2 +- lsfg-vk-layer/src/config.cpp | 238 ------------------ lsfg-vk-layer/src/config.hpp | 69 ----- lsfg-vk-layer/src/configuration/config.cpp | 36 +-- lsfg-vk-layer/src/configuration/config.hpp | 10 +- lsfg-vk-layer/src/context/instance.cpp | 149 +++++------ lsfg-vk-layer/src/context/instance.hpp | 38 +-- lsfg-vk-layer/src/detection.cpp | 121 --------- lsfg-vk-layer/src/detection.hpp | 40 --- lsfg-vk-layer/src/entrypoint.cpp | 64 ++--- lsfg-vk-layer/src/layer.cpp | 77 ------ lsfg-vk-layer/src/layer.hpp | 54 ---- 12 files changed, 122 insertions(+), 776 deletions(-) delete mode 100644 lsfg-vk-layer/src/config.cpp delete mode 100644 lsfg-vk-layer/src/config.hpp delete mode 100644 lsfg-vk-layer/src/detection.cpp delete mode 100644 lsfg-vk-layer/src/detection.hpp delete mode 100644 lsfg-vk-layer/src/layer.cpp delete mode 100644 lsfg-vk-layer/src/layer.hpp diff --git a/lsfg-vk-layer/VkLayer_LS_frame_generation.json b/lsfg-vk-layer/VkLayer_LS_frame_generation.json index 03c3173..2c1e5e4 100644 --- a/lsfg-vk-layer/VkLayer_LS_frame_generation.json +++ b/lsfg-vk-layer/VkLayer_LS_frame_generation.json @@ -8,7 +8,7 @@ "type": "GLOBAL", "api_version": "1.4.328", "disable_environment": { - "DISABLE_LSFG": "1" + "DISABLE_LSFGVK": "1" } } } diff --git a/lsfg-vk-layer/src/config.cpp b/lsfg-vk-layer/src/config.cpp deleted file mode 100644 index 9bbba91..0000000 --- a/lsfg-vk-layer/src/config.cpp +++ /dev/null @@ -1,238 +0,0 @@ -#include "config.hpp" -#include "lsfg-vk-backend/lsfgvk.hpp" - -#include -#include -#include -#include -#include -#include -#include - -#define TOML_ENABLE_FORMATTERS 0 -#include - -using namespace lsfgvk::layer; - -namespace { - const char* DEFAULT_CONFIG = R"(version = 2 - -[global] -# dll = '/media/games/Lossless Scaling/Lossless.dll' # if you don't have LS in the default location -allow_fp16 = true # this will improve give a MASSIVE performance boost on AMD, but be super slow on older (!) NVIDIA GPUs - -[[profile]] -name = "4x FG / 85% [Performance]" -active_in = [ # see the wiki for more info - 'vkcube', - 'vkcubepp' -] -multiplier = 4 -flow_scale = 0.85 -performance_mode = true -pacing = 'none' # see the wiki for more info - -[[profile]] -name = "2x FG / 100%" -active_in = 'GenshinImpact.exe' -multiplier = 2 -)"; - - /// parse an activity array from toml value - std::vector activityFromString(const toml::node_view& val) { - std::vector active_in{}; - - if (const auto& as_str = val.value()) { - active_in.push_back(*as_str); - } - - if (const auto& as_arr = val.as_array()) { - for (const auto& item : *as_arr) { - if (const auto& item_str = item.value()) - active_in.push_back(*item_str); - } - } - - return active_in; - } - /// parse a pacing method from string - Pacing parcingFromString(const std::string& str) { - if (str == "none") - return Pacing::None; - throw lsfgvk::error("unknown pacing method: " + str); - } - /// try to find the config - std::filesystem::path findPath() { - // always honor LSFGVK_CONFIG if set - const char* envPath = std::getenv("LSFGVK_CONFIG"); - if (envPath && *envPath != '\0') - return{envPath}; - - // then check the XDG overriden location - const char* xdgPath = std::getenv("XDG_CONFIG_HOME"); - if (xdgPath && *xdgPath != '\0') - return std::filesystem::path(xdgPath) - / "lsfg-vk" / "conf.toml"; - - // fallback to typical user home - const char* homePath = std::getenv("HOME"); - if (homePath && *homePath != '\0') - return std::filesystem::path(homePath) - / ".config" / "lsfg-vk" / "conf.toml"; - - // finally, use system-wide config - return "/etc/lsfg-vk/conf.toml"; - } - /// parse the global configuration - GlobalConf parseGlobalConf(const toml::table& tbl) { - const GlobalConf conf{ - .dll = tbl["dll"].value(), - .allow_fp16 = tbl["allow_fp16"].value_or(true) - }; - - if (conf.dll && !std::filesystem::exists(*conf.dll)) - throw lsfgvk::error("path to dll is invalid"); - - return conf; - } - /// parse a game profile configuration - GameConf parseGameConf(const toml::table& tbl) { - const GameConf conf{ - .name = tbl["name"].value_or("unnamed"), - .active_in = activityFromString(tbl["active_in"]), - .multiplier = tbl["multiplier"].value_or(2U), - .flow_scale = tbl["flow_scale"].value_or(1.0F), - .performance_mode = tbl["performance_mode"].value_or(false), - .pacing = parcingFromString(tbl["pacing"].value_or("none")) - }; - - if (conf.multiplier <= 1) - throw lsfgvk::error("multiplier must be greater than 1"); - if (conf.flow_scale < 0.25F || conf.flow_scale > 1.0F) - throw lsfgvk::error("flow_scale must be between 0.25 and 1.0"); - - return conf; - } - /// parse the global configuration from the environment - GlobalConf parseGlobalConfFromEnv() { - GlobalConf conf{ - .dll = std::nullopt, - .allow_fp16 = true - }; - - const char* dll = std::getenv("LSFGVK_DLL_PATH"); - if (dll && *dll != '\0') - conf.dll = std::string(dll); - const char* no_fp16 = std::getenv("LSFGVK_NO_FP16"); - if (no_fp16 && *no_fp16 != '\0') - conf.allow_fp16 = std::string(no_fp16) != "1"; - - if (conf.dll && !std::filesystem::exists(*conf.dll)) - throw lsfgvk::error("path to dll is invalid"); - - return conf; - } - /// parse a game profile configuration from the environment - GameConf parseGameConfFromEnv() { - GameConf conf{ - .name = "(environment)", - .active_in = {}, - - .multiplier = 2, - .flow_scale = 1.0F, - .performance_mode = false, - .pacing = Pacing::None - }; - - const char* multiplier = std::getenv("LSFGVK_MULTIPLIER"); - if (multiplier) conf.multiplier = static_cast(std::stoul(multiplier)); - const char* flow_scale = std::getenv("LSFGVK_FLOW_SCALE"); - if (flow_scale) conf.flow_scale = std::stof(flow_scale); - const char* performance = std::getenv("LSFGVK_PERFORMANCE_MODE"); - if (performance) conf.performance_mode = std::string(performance) == "1"; - const char* pacing = std::getenv("LSFGVK_PACING"); - if (pacing) conf.pacing = parcingFromString(std::string(pacing)); - - if (conf.multiplier <= 1) - throw lsfgvk::error("multiplier must be greater than 1"); - if (conf.flow_scale < 0.25F || conf.flow_scale > 1.0F) - throw lsfgvk::error("flow_scale must be between 0.25 and 1.0"); - - return conf; - } -} - -Configuration::Configuration() : - path(findPath()), - from_env(std::getenv("LSFGVK_ENV") != nullptr) { - if (std::filesystem::exists(this->path) || this->from_env) - return; - - try { - std::filesystem::create_directories(this->path.parent_path()); - if (!std::filesystem::exists(this->path.parent_path())) - throw lsfgvk::error("unable to create configuration directory"); - - std::ofstream ofs(this->path); - if (!ofs.is_open()) - throw lsfgvk::error("unable to create default configuration file"); - - ofs << DEFAULT_CONFIG; - ofs.close(); - } catch (const std::filesystem::filesystem_error& e) { - throw lsfgvk::error("unable to create default configuration file", e); - } -} - -bool Configuration::tick() { - if (this->from_env) { - if (this->profiles.empty()) { - this->global = parseGlobalConfFromEnv(); - this->profiles.push_back(parseGameConfFromEnv()); - return true; - } - - return false; // no need to tick if from env - } - - // check for updates - try { - auto time = std::filesystem::last_write_time(this->path); - if (time == this->timestamp) - return false; - - this->timestamp = time; - } catch (const std::filesystem::filesystem_error& e) { - throw lsfgvk::error("unable to access configuration file", e); - } - - // parse configuration - GlobalConf global{}; - std::vector profiles{}; - - toml::table tbl; - try { - tbl = toml::parse_file(this->path.string()); - } catch (const toml::parse_error& e) { - throw lsfgvk::error("unable to parse configuration", e); - } - - auto vrs = tbl["version"]; - if (!vrs || !vrs.is_integer() || *vrs.as_integer() != 2) - throw lsfgvk::error("unsupported configuration version"); - - auto gbl = tbl["global"]; - if (gbl && gbl.is_table()) { - global = parseGlobalConf(*gbl.as_table()); - } - - auto pfls = tbl["profile"]; - if (pfls && pfls.is_array_of_tables()) { - for (const auto& pfl : *pfls.as_array()) - profiles.push_back(parseGameConf(*pfl.as_table())); - } - - this->global = std::move(global); - this->profiles = std::move(profiles); - return true; -} diff --git a/lsfg-vk-layer/src/config.hpp b/lsfg-vk-layer/src/config.hpp deleted file mode 100644 index 0c7a8b4..0000000 --- a/lsfg-vk-layer/src/config.hpp +++ /dev/null @@ -1,69 +0,0 @@ -#pragma once - -#include -#include -#include -#include -#include - -namespace lsfgvk::layer { - - /// global configuration - struct GlobalConf { - /// optional dll override - std::optional dll; - /// should fp16 be allowed - bool allow_fp16; - }; - - /// pacing methods - enum class Pacing { - /// do not perform any pacing (vsync+novrr) - None - }; - - /// game profile configuration - struct GameConf { - /// name of the profile - std::string name; - /// optional activation string/array - std::vector active_in; - /// multiplier for frame generation - size_t multiplier; - /// non-inverted flow scale - float flow_scale; - /// use performance mode - bool performance_mode; - /// pacing method - Pacing pacing; - }; - - /// automatically updating configuration - class Configuration { - public: - /// create a new configuration - /// @throws lsfgvk::error on failure - Configuration(); - - /// reload the configuration from disk if the file has changed - /// @throws lsfgvk::error on failure - /// @return true if the configuration was reloaded - bool tick(); - - /// get the global configuration - /// @return global configuration - [[nodiscard]] const GlobalConf& getGlobalConf() const { return global; } - - /// get the game profiles - /// @return list of game profiles - [[nodiscard]] const std::vector& getProfiles() const { return profiles; } - private: - std::filesystem::path path; - std::chrono::time_point timestamp; - bool from_env{}; - - GlobalConf global; - std::vector profiles; - }; - -} diff --git a/lsfg-vk-layer/src/configuration/config.cpp b/lsfg-vk-layer/src/configuration/config.cpp index cae857b..40ec34a 100644 --- a/lsfg-vk-layer/src/configuration/config.cpp +++ b/lsfg-vk-layer/src/configuration/config.cpp @@ -171,7 +171,13 @@ multiplier = 2 Configuration::Configuration() : path(findPath()), from_env(std::getenv("LSFGVK_ENV") != nullptr) { - if (std::filesystem::exists(this->path) || this->from_env) + if (this->from_env) { + this->global = parseGlobalConfFromEnv(); + this->profiles.push_back(parseGameConfFromEnv()); + return; + } + + if (std::filesystem::exists(this->path)) return; try { @@ -190,29 +196,24 @@ Configuration::Configuration() : } } -bool Configuration::tick() { - if (this->from_env) { - if (this->profiles.empty()) { - this->global = parseGlobalConfFromEnv(); - this->profiles.push_back(parseGameConfFromEnv()); - return true; - } +bool Configuration::isUpToDate() { + if (this->from_env) + return true; - return false; // no need to tick if from env - } - - // check for updates try { - auto time = std::filesystem::last_write_time(this->path); - if (time == this->timestamp) - return false; + return std::filesystem::last_write_time(this->path) == this->timestamp; + } catch (const std::filesystem::filesystem_error& e) { + throw lsfgvk::error("unable to access configuration file", e); + } +} - this->timestamp = time; +void Configuration::reload() { + try { + this->timestamp = std::filesystem::last_write_time(this->path); } catch (const std::filesystem::filesystem_error& e) { throw lsfgvk::error("unable to access configuration file", e); } - // parse configuration GlobalConf global{}; std::vector profiles{}; @@ -240,5 +241,4 @@ bool Configuration::tick() { this->global = std::move(global); this->profiles = std::move(profiles); - return true; } diff --git a/lsfg-vk-layer/src/configuration/config.hpp b/lsfg-vk-layer/src/configuration/config.hpp index c8afee8..2b39235 100644 --- a/lsfg-vk-layer/src/configuration/config.hpp +++ b/lsfg-vk-layer/src/configuration/config.hpp @@ -47,10 +47,14 @@ namespace lsfgvk::layer { /// @throws lsfgvk::error on failure Configuration(); - /// reload the configuration from disk if the file has changed + /// check if the configuration is out of date /// @throws lsfgvk::error on failure - /// @return true if the configuration was reloaded - bool tick(); + /// @return true if the configuration is out of date + bool isUpToDate(); + + /// reload the configuration from disk + /// @throws lsfgvk::error on failure + void reload(); /// get the global configuration /// @return global configuration diff --git a/lsfg-vk-layer/src/context/instance.cpp b/lsfg-vk-layer/src/context/instance.cpp index 14964de..91bf59f 100644 --- a/lsfg-vk-layer/src/context/instance.cpp +++ b/lsfg-vk-layer/src/context/instance.cpp @@ -2,7 +2,6 @@ #include "../configuration/config.hpp" #include "../configuration/detection.hpp" #include "lsfg-vk-backend/lsfgvk.hpp" -#include "lsfg-vk-common/vulkan/vulkan.hpp" #include #include @@ -15,69 +14,8 @@ using namespace lsfgvk; using namespace lsfgvk::layer; -Root::Root() : identification(identify()) { - this->tick(); - - if (!this->profile.has_value()) - return; - - std::cerr << "lsfg-vk: using profile with name '" << this->profile->name << "' "; - switch (this->identType) { - case IdentType::OVERRIDE: - std::cerr << "(identified via override)\n"; - break; - case IdentType::EXECUTABLE: - std::cerr << "(identified via executable)\n"; - break; - case IdentType::WINE_EXECUTABLE: - std::cerr << "(identified via wine executable)\n"; - break; - case IdentType::PROCESS_NAME: - std::cerr << "(identified via process name)\n"; - break; - } -} - -bool Root::tick() { - auto res = this->config.tick(); - if (!res) - return false; - - // try to find a profile - const auto& detec = findProfile(this->config, identification); - if (!detec.has_value()) - return this->profile.has_value(); - - this->identType = detec->first; - this->profile = detec->second; - return true; -} - -std::vector Root::instanceExtensions() const { - if (!this->profile.has_value()) - return {}; - - return { - "VK_KHR_get_physical_device_properties2", - "VK_KHR_external_memory_capabilities", - "VK_KHR_external_semaphore_capabilities" - }; -} - -std::vector Root::deviceExtensions() const { - if (!this->profile.has_value()) - return {}; - - return { - "VK_KHR_external_memory", - "VK_KHR_external_memory_fd", - "VK_KHR_external_semaphore", - "VK_KHR_external_semaphore_fd", - "VK_KHR_timeline_semaphore" - }; -} - namespace { + // find the shader dll std::filesystem::path findShaderDll() { const std::vector FRAGMENTS{{ ".local/share/Steam/steamapps/common", @@ -118,32 +56,73 @@ namespace { throw lsfgvk::error("unable to locate Lossless.dll, please set the path in the configuration"); } +} - lsfgvk::Instance createBackend(const Root& root) { - const auto& conf = root.conf(); - const auto& profile = root.active(); - if (!profile.has_value()) // should not happen - throw lsfgvk::error("no profile active"); +Root::Root() { + // find active profile + this->config.reload(); + const auto& profile = findProfile(this->config, identify()); + if (!profile.has_value()) + return; - return { - [profile = *profile]( - const std::string& deviceName, - std::pair ids, - const std::optional& pci - ) { - if (!profile.gpu) - return true; + this->active_profile = profile->second; - return (deviceName == *profile.gpu) - || (ids.first + ":" + ids.second == *profile.gpu) - || (pci && *pci == *profile.gpu); - }, - conf.dll.value_or(findShaderDll()), - conf.allow_fp16 - }; + std::cerr << "lsfg-vk: using profile with name '" << this->active_profile->name << "' "; + switch (profile->first) { + case IdentType::OVERRIDE: + std::cerr << "(identified via override)\n"; + break; + case IdentType::EXECUTABLE: + std::cerr << "(identified via executable)\n"; + break; + case IdentType::WINE_EXECUTABLE: + std::cerr << "(identified via wine executable)\n"; + break; + case IdentType::PROCESS_NAME: + std::cerr << "(identified via process name)\n"; + break; } + + // create backend + /*const auto& global = this->config.getGlobalConf(); + this->backend.emplace( + [gpu = profile->second.gpu]( + const std::string& deviceName, + std::pair ids, + const std::optional& pci + ) { + if (!gpu) + return true; + + return (deviceName == *gpu) + || (ids.first + ":" + ids.second == *gpu) + || (pci && *pci == *gpu); + }, + global.dll.value_or(findShaderDll()), + global.allow_fp16 + );*/ } -layer::Instance::Instance(const Root& root, vk::Vulkan vk) - : vk(std::move(vk))/*, backend(createBackend(layer))*/ { +std::vector Root::instanceExtensions() const { + if (!this->active_profile.has_value()) + return {}; + + return { + "VK_KHR_get_physical_device_properties2", + "VK_KHR_external_memory_capabilities", + "VK_KHR_external_semaphore_capabilities" + }; +} + +std::vector Root::deviceExtensions() const { + if (!this->active_profile.has_value()) + return {}; + + return { + "VK_KHR_external_memory", + "VK_KHR_external_memory_fd", + "VK_KHR_external_semaphore", + "VK_KHR_external_semaphore_fd", + "VK_KHR_timeline_semaphore" + }; } diff --git a/lsfg-vk-layer/src/context/instance.hpp b/lsfg-vk-layer/src/context/instance.hpp index 24dc7a7..2a75f09 100644 --- a/lsfg-vk-layer/src/context/instance.hpp +++ b/lsfg-vk-layer/src/context/instance.hpp @@ -1,29 +1,24 @@ #pragma once #include "../configuration/config.hpp" -#include "../configuration/detection.hpp" #include "lsfg-vk-backend/lsfgvk.hpp" #include "lsfg-vk-common/helpers/pointers.hpp" -#include "lsfg-vk-common/vulkan/vulkan.hpp" #include #include namespace lsfgvk::layer { - /// root of the lsfg-vk layer + /// root context of the lsfg-vk layer class Root { public: - /// create a new root + /// create the lsfg-vk root context /// @throws lsfgvk::error on failure Root(); - /// get the global configuration - /// @return configuration - [[nodiscard]] const auto& conf() const { return config.getGlobalConf(); } - /// get the active profile - /// @return game configuration - [[nodiscard]] const auto& active() const { return profile; } + /// check if the layer is active + /// @return true if active + [[nodiscard]] bool active() const { return this->active_profile.has_value(); } /// required instance extensions /// @return list of extension names @@ -31,30 +26,11 @@ namespace lsfgvk::layer { /// required device extensions /// @return list of extension names [[nodiscard]] std::vector deviceExtensions() const; - - /// tick the root - /// @throws lsfgvk::error on failure - /// @return true if profile changed - bool tick(); private: Configuration config; - Identification identification; + std::optional active_profile; - IdentType identType{}; // type used to deduce the profile - std::optional profile; - }; - - - /// instance of the lsfg-vk layer on a VkInstance/VkDevice pair. - class Instance { - public: - /// create a new layer instance - /// @param root root of the layer - /// @param vk vulkan instance - Instance(const Root& root, vk::Vulkan vk); - private: - vk::Vulkan vk; - ls::lazy backend; // lazy due to KhronosGroup/Vulkan-Loader#1739 + ls::lazy backend; }; } diff --git a/lsfg-vk-layer/src/detection.cpp b/lsfg-vk-layer/src/detection.cpp deleted file mode 100644 index e4144d5..0000000 --- a/lsfg-vk-layer/src/detection.cpp +++ /dev/null @@ -1,121 +0,0 @@ -#include "detection.hpp" -#include "config.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -using namespace lsfgvk; -using namespace lsfgvk::layer; - -namespace { - // try to match a profile by id - std::optional match(const std::vector& profiles, const std::string& id) { - for (const auto& profile : profiles) - for (const auto& activation : profile.active_in) - if (activation == id) - return profile; - return std::nullopt; - } -} - -Identification layer::identify() { - Identification id{}; - - // fetch LSFGVK_PROFILE - const char* override = std::getenv("LSFGVK_PROFILE"); - if (override && *override != '\0') - id.override = std::string(override); - - // fetch process exe path - std::array buf{}; - const ssize_t len = readlink("/proc/self/exe", buf.data(), buf.size() - 1); - if (len > 0) { - buf.at(static_cast(len)) = '\0'; - id.executable = std::string(buf.data()); - } - - // if running under wine, fetch the actual exe path - if (id.executable.find("wine") != std::string::npos - || id.executable.find("proton") != std::string::npos) { - - std::ifstream maps("/proc/self/maps"); - std::string line; - while (maps.is_open() && std::getline(maps, line)) { - if (!line.ends_with(".exe")) - continue; - - size_t pos = line.find_first_of('/'); - if (pos == std::string::npos) { - pos = line.find_last_of(' '); - if (pos == std::string::npos) - continue; - pos += 1; // skip space - } - - const std::string wine_executable = line.substr(pos); - if (wine_executable.empty()) - continue; - - id.wine_executable = wine_executable; - break; - } - } - - // fetch process name - std::ifstream comm("/proc/self/comm"); - if (comm.is_open()) { - comm.read(buf.data(), buf.size() - 1); - buf.at(static_cast(comm.gcount())) = '\0'; - - id.process_name = std::string(buf.data()); - if (id.process_name.back() == '\n') - id.process_name.pop_back(); - } - - return id; -} - -std::optional> layer::findProfile( - const Configuration& config, const Identification& id) { - const auto& profiles = config.getProfiles(); - - // check for the environment option first - if (std::getenv("LSFGVK_ENV") != nullptr) - return std::make_pair(IdentType::OVERRIDE, config.getProfiles().front()); - - // then override first - if (id.override.has_value()) { - const auto profile = match(profiles, id.override.value()); - if (profile.has_value()) - return std::make_pair(IdentType::OVERRIDE, profile.value()); - } - - // then check executable - const auto exe_profile = match(profiles, id.executable); - if (exe_profile.has_value()) - return std::make_pair(IdentType::EXECUTABLE, exe_profile.value()); - - // if present, check wine executable next - if (id.wine_executable.has_value()) { - const auto wine_profile = match(profiles, id.wine_executable.value()); - if (wine_profile.has_value()) - return std::make_pair(IdentType::WINE_EXECUTABLE, wine_profile.value()); - } - - // finally, fallback to process name - if (!id.process_name.empty()) { - const auto proc_profile = match(profiles, id.process_name); - if (proc_profile.has_value()) - return std::make_pair(IdentType::PROCESS_NAME, proc_profile.value()); - } - - return std::nullopt; -} diff --git a/lsfg-vk-layer/src/detection.hpp b/lsfg-vk-layer/src/detection.hpp deleted file mode 100644 index 5ef9f32..0000000 --- a/lsfg-vk-layer/src/detection.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once - -#include "config.hpp" - -#include -#include -#include - -namespace lsfgvk::layer { - - /// identification data for a process - struct Identification { - /// optional override name - std::optional override; - /// path to exe file - std::string executable; - /// path to exe file when running under wine - std::optional wine_executable; - /// traditional process name (e.g. GameThread) - std::string process_name; - }; - - /// enum describing which identification method was used - enum class IdentType { - OVERRIDE, // identified by override - EXECUTABLE, // identified by executable path - WINE_EXECUTABLE, // identified by wine executable path - PROCESS_NAME // identified by process name - }; - - /// identify the current process - Identification identify(); - - /// find a profile for the current process - /// @param config configuration to search in - /// @param id identification data - /// @return ident pair if found - std::optional> findProfile( - const Configuration& config, const Identification& id); -} diff --git a/lsfg-vk-layer/src/entrypoint.cpp b/lsfg-vk-layer/src/entrypoint.cpp index 3cca3f5..26d18ed 100644 --- a/lsfg-vk-layer/src/entrypoint.cpp +++ b/lsfg-vk-layer/src/entrypoint.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -37,22 +36,6 @@ namespace { } namespace { - // device-wide info initialized at device creation - struct DeviceInfo { - VkDevice handle; - vk::VulkanDeviceFuncs funcs; - - layer::Instance layer; - }; - - // instance-wide info initialized at instance creation - struct InstanceInfo { - VkInstance handle; - vk::VulkanInstanceFuncs funcs; - - std::unordered_map devices; - }* instance_info; - // global layer info initialized at layer negotiation struct LayerInfo { std::unordered_map map; //!< function pointer override map @@ -61,6 +44,14 @@ namespace { layer::Root root; }* layer_info; + // instance-wide info initialized at instance creation + struct InstanceInfo { + VkInstance handle; + vk::VulkanInstanceFuncs funcs; + + std::unordered_map devices; + }* instance_info; + // create instance VkResult myvkCreateInstance( const VkInstanceCreateInfo* info, @@ -201,19 +192,11 @@ namespace { try { instance_info->devices.emplace( *device, - new DeviceInfo{ - .handle = *device, - .funcs = vk::initVulkanDeviceFuncs(instance_info->funcs, *device), - .layer = layer::Instance( - layer_info->root, - vk::Vulkan( - instance_info->handle, *device, physdev, - instance_info->funcs, - vk::initVulkanDeviceFuncs(instance_info->funcs, *device), - true, setLoaderData - ) - ) - } + vk::Vulkan( + instance_info->handle, *device, physdev, + instance_info->funcs, vk::initVulkanDeviceFuncs(instance_info->funcs, *device), + true, setLoaderData + ) ); } catch (const std::exception& e) { std::cerr << "lsfg-vk: something went wrong during lsfg-vk initialization:\n"; @@ -227,10 +210,8 @@ namespace { void myvkDestroyDevice(VkDevice device, const VkAllocationCallbacks* alloc) { // destroy layer instance auto it = instance_info->devices.find(device); - if (it != instance_info->devices.end()) { - delete it->second; + if (it != instance_info->devices.end()) instance_info->devices.erase(it); - } // destroy device auto vkDestroyDevice = reinterpret_cast( @@ -316,11 +297,7 @@ VkResult vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVers // load the layer configuration try { - layer::Root root{}; - if (!root.active()) // skip inactive - return VK_ERROR_INITIALIZATION_FAILED; - - layer_info = new LayerInfo{ + layer_info = new LayerInfo { .map = { #define VKPTR(name) reinterpret_cast(name) { "vkCreateInstance", VKPTR(myvkCreateInstance) }, @@ -329,11 +306,20 @@ VkResult vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVers { "vkDestroyInstance", VKPTR(myvkDestroyInstance) } #undef VKPTR }, - .root = std::move(root) + .root = layer::Root() }; + + if (!layer_info->root.active()) { // skip inactive + delete layer_info; + layer_info = nullptr; + + return VK_ERROR_INITIALIZATION_FAILED; + } } catch (const std::exception& e) { std::cerr << "lsfg-vk: something went wrong during lsfg-vk layer initialization:\n"; std::cerr << "- " << e.what() << '\n'; + + return VK_ERROR_INITIALIZATION_FAILED; } // emplace function pointers/version diff --git a/lsfg-vk-layer/src/layer.cpp b/lsfg-vk-layer/src/layer.cpp deleted file mode 100644 index db9caf8..0000000 --- a/lsfg-vk-layer/src/layer.cpp +++ /dev/null @@ -1,77 +0,0 @@ -#include "layer.hpp" -#include "detection.hpp" -#include "lsfg-vk-common/vulkan/vulkan.hpp" - -#include -#include -#include - -using namespace lsfgvk; -using namespace lsfgvk::layer; - -Layer::Layer() : identification(identify()) { - this->tick(); - - if (!this->profile.has_value()) - return; - - std::cerr << "lsfg-vk: using profile with name '" << this->profile->name << "' "; - switch (this->identType) { - case IdentType::OVERRIDE: - std::cerr << "(identified via override)\n"; - break; - case IdentType::EXECUTABLE: - std::cerr << "(identified via executable)\n"; - break; - case IdentType::WINE_EXECUTABLE: - std::cerr << "(identified via wine executable)\n"; - break; - case IdentType::PROCESS_NAME: - std::cerr << "(identified via process name)\n"; - break; - } -} - -bool Layer::tick() { - auto res = this->config.tick(); - if (!res) - return false; - - // try to find a profile - const auto& detec = findProfile(this->config, identification); - if (!detec.has_value()) - return this->profile.has_value(); - - this->identType = detec->first; - this->profile = detec->second; - return true; -} - -std::vector Layer::instanceExtensions() const { - if (!this->profile.has_value()) - return {}; - - return { - "VK_KHR_get_physical_device_properties2", - "VK_KHR_external_memory_capabilities", - "VK_KHR_external_semaphore_capabilities" - }; -} - -std::vector Layer::deviceExtensions() const { - if (!this->profile.has_value()) - return {}; - - return { - "VK_KHR_external_memory", - "VK_KHR_external_memory_fd", - "VK_KHR_external_semaphore", - "VK_KHR_external_semaphore_fd", - "VK_KHR_timeline_semaphore" - }; -} - -layer::LayerInstance::LayerInstance(const Layer& layer, vk::Vulkan vk) - : vk(std::move(vk)) { - -} diff --git a/lsfg-vk-layer/src/layer.hpp b/lsfg-vk-layer/src/layer.hpp deleted file mode 100644 index 0e5314b..0000000 --- a/lsfg-vk-layer/src/layer.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#pragma once - -#include "config.hpp" -#include "detection.hpp" -#include "lsfg-vk-common/vulkan/vulkan.hpp" - -#include -#include - -namespace lsfgvk::layer { - - /// lsfg-vk layer - class Layer { - public: - /// create a new layer - /// @throws lsfgvk::error on failure - Layer(); - - /// get the active profile - /// @return game configuration - [[nodiscard]] const auto& active() const { return profile; } - - /// required instance extensions - /// @return list of extension names - [[nodiscard]] std::vector instanceExtensions() const; - /// required device extensions - /// @return list of extension names - [[nodiscard]] std::vector deviceExtensions() const; - - /// tick the layer - /// @throws lsfgvk::error on failure - /// @return true if profile changed - bool tick(); - private: - Configuration config; - Identification identification; - - IdentType identType{}; // type used to deduce the profile - std::optional profile; - }; - - - /// instance of the lsfg-vk layer on a VkInstance/VkDevice pair. - class LayerInstance { - public: - /// create a new layer instance - /// @param layer parent layer - /// @param vk vulkan instance - LayerInstance(const Layer& layer, vk::Vulkan vk); - private: - vk::Vulkan vk; - }; - -}