diff --git a/src/dxvk/dxvk_instance.cpp b/src/dxvk/dxvk_instance.cpp index bc96b5c43..692829e33 100644 --- a/src/dxvk/dxvk_instance.cpp +++ b/src/dxvk/dxvk_instance.cpp @@ -11,8 +11,8 @@ namespace dxvk { Logger::info(str::format("Game: ", env::getExeName())); Logger::info(str::format("DXVK: ", DXVK_VERSION)); - m_config = getUserConfig(); - m_config.merge(getAppConfig(env::getExeName())); + m_config = Config::getUserConfig(); + m_config.merge(Config::getAppConfig(env::getExeName())); g_vrInstance.initInstanceExtensions(); diff --git a/src/dxvk/dxvk_instance.h b/src/dxvk/dxvk_instance.h index 4b88a9afe..d2b324262 100644 --- a/src/dxvk/dxvk_instance.h +++ b/src/dxvk/dxvk_instance.h @@ -1,6 +1,6 @@ #pragma once -#include "../util/config/config_user.h" +#include "../util/config/config.h" #include "dxvk_adapter.h" #include "dxvk_device.h" diff --git a/src/util/config/config.cpp b/src/util/config/config.cpp index e9f05527a..d87f2b7da 100644 --- a/src/util/config/config.cpp +++ b/src/util/config/config.cpp @@ -1,7 +1,86 @@ +#include +#include +#include + #include "config.h" +#include "../log/log.h" + +#include "../util_env.h" + namespace dxvk { + const static std::unordered_map g_appDefaults = {{ + { "Dishonored2.exe", {{ + { "d3d11.allowMapFlagNoWait", "True" } + }} }, + { "F1_2015.exe", {{ + { "d3d11.fakeStreamOutSupport", "True" }, + }} }, + { "FarCry5.exe", {{ + { "d3d11.allowMapFlagNoWait", "True" } + }} }, + { "Frostpunk.exe", {{ + { "dxgi.deferSurfaceCreation", "True" }, + }} }, + { "Overwatch.exe", {{ + { "d3d11.fakeStreamOutSupport", "True" }, + }} }, + { "Wow.exe", {{ + { "dxgi.fakeDx10Support", "True" }, + }} }, + { "ffxv_s.exe", {{ + { "d3d11.fakeStreamOutSupport", "True" }, + }} }, + { "mafia3.exe", {{ + { "d3d11.fakeStreamOutSupport", "True" }, + }} }, + }}; + + + static bool isWhitespace(char ch) { + return ch == ' ' || ch == '\x9' || ch == '\r'; + } + + + static bool isValidKeyChar(char ch) { + return (ch >= '0' && ch <= '9') + || (ch >= 'A' && ch <= 'Z') + || (ch >= 'a' && ch <= 'z') + || (ch == '.' || ch == '_'); + } + + + static size_t skipWhitespace(const std::string& line, size_t n) { + while (n < line.size() && isWhitespace(line[n])) + n += 1; + return n; + } + + + static void parseUserConfigLine(Config& config, const std::string& line) { + std::stringstream key; + std::stringstream value; + + // Extract the key + size_t n = skipWhitespace(line, 0); + while (n < line.size() && isValidKeyChar(line[n])) + key << line[n++]; + + // Check whether the next char is a '=' + n = skipWhitespace(line, n); + if (n >= line.size() || line[n] != '=') + return; + + // Extract the value + n = skipWhitespace(line, n + 1); + while (n < line.size() && !isWhitespace(line[n])) + value << line[n++]; + + config.setOption(key.str(), value.str()); + } + + Config::Config() { } Config::~Config() { } @@ -83,4 +162,37 @@ namespace dxvk { return true; } + + Config Config::getAppConfig(const std::string& appName) { + auto appConfig = g_appDefaults.find(appName); + if (appConfig != g_appDefaults.end()) + return appConfig->second; + return Config(); + } + + + Config Config::getUserConfig() { + Config config; + + // Load either $DXVK_CONFIG_FILE or $PWD/dxvk.conf + std::string filePath = env::getEnvVar(L"DXVK_CONFIG_FILE"); + + if (filePath == "") + filePath = "dxvk.conf"; + + // Open the file if it exists + std::ifstream stream(filePath); + + if (!stream) + return config; + + // Parse the file line by line + std::string line; + + while (std::getline(stream, line)) + parseUserConfigLine(config, line); + + return config; + } + } \ No newline at end of file diff --git a/src/util/config/config.h b/src/util/config/config.h index dd0ae951f..bad14fd53 100644 --- a/src/util/config/config.h +++ b/src/util/config/config.h @@ -65,6 +65,23 @@ namespace dxvk { return result; } + /** + * \brief Retrieves default options for an app + * + * \param [in] appName Name of the application + * \returns Default options for the application + */ + static Config getAppConfig(const std::string& appName); + + /** + * \brief Retrieves user configuration + * + * Reads options from the configuration file, + * if it can be found, or an empty option set. + * \returns User-defined configuration options + */ + static Config getUserConfig(); + private: OptionMap m_options; diff --git a/src/util/config/config_user.cpp b/src/util/config/config_user.cpp deleted file mode 100644 index 49d9f355f..000000000 --- a/src/util/config/config_user.cpp +++ /dev/null @@ -1,112 +0,0 @@ -#include -#include -#include - -#include "config.h" -#include "config_user.h" - -#include "../log/log.h" - -namespace dxvk { - - void parseUserConfigLine(Config& config, std::string line); - - const static std::unordered_map g_appDefaults = {{ - { "Dishonored2.exe", {{ - { "d3d11.allowMapFlagNoWait", "True" } - }} }, - { "F1_2015.exe", {{ - { "d3d11.fakeStreamOutSupport", "True" }, - }} }, - { "FarCry5.exe", {{ - { "d3d11.allowMapFlagNoWait", "True" } - }} }, - { "Frostpunk.exe", {{ - { "dxgi.deferSurfaceCreation", "True" }, - }} }, - { "Overwatch.exe", {{ - { "d3d11.fakeStreamOutSupport", "True" }, - }} }, - { "Wow.exe", {{ - { "dxgi.fakeDx10Support", "True" }, - }} }, - { "ffxv_s.exe", {{ - { "d3d11.fakeStreamOutSupport", "True" }, - }} }, - { "mafia3.exe", {{ - { "d3d11.fakeStreamOutSupport", "True" }, - }} }, - }}; - - - Config getAppConfig(const std::string& appName) { - auto appConfig = g_appDefaults.find(appName); - if (appConfig != g_appDefaults.end()) - return appConfig->second; - return Config(); - } - - - Config getUserConfig() { - Config config; - - // Load either $DXVK_CONFIG_FILE or $PWD/dxvk.conf - std::string filePath = env::getEnvVar(L"DXVK_CONFIG_FILE"); - - if (filePath == "") - filePath = "dxvk.conf"; - - // Parse the file line by line - std::ifstream stream(filePath); - std::string line; - - while (std::getline(stream, line)) - parseUserConfigLine(config, line); - - return config; - } - - - bool isWhitespace(char ch) { - return ch == ' ' || ch == '\x9' || ch == '\r'; - } - - - bool isValidKeyChar(char ch) { - return (ch >= '0' && ch <= '9') - || (ch >= 'A' && ch <= 'Z') - || (ch >= 'a' && ch <= 'z') - || (ch == '.' || ch == '_'); - } - - - size_t skipWhitespace(const std::string& line, size_t n) { - while (n < line.size() && isWhitespace(line[n])) - n += 1; - return n; - } - - - void parseUserConfigLine(Config& config, std::string line) { - std::stringstream key; - std::stringstream value; - - // Extract the key - size_t n = skipWhitespace(line, 0); - while (n < line.size() && isValidKeyChar(line[n])) - key << line[n++]; - - // Check whether the next char is a '=' - n = skipWhitespace(line, n); - if (n >= line.size() || line[n] != '=') - return; - - // Extract the value - n = skipWhitespace(line, n + 1); - while (n < line.size() && !isWhitespace(line[n])) - value << line[n++]; - - config.setOption(key.str(), value.str()); - } - -} \ No newline at end of file diff --git a/src/util/config/config_user.h b/src/util/config/config_user.h deleted file mode 100644 index d98117cf7..000000000 --- a/src/util/config/config_user.h +++ /dev/null @@ -1,30 +0,0 @@ -#pragma once - -#include "../util_env.h" - -#include "config.h" - -namespace dxvk { - - /** - * \brief Retrieves application defaults - * - * Some apps have options enabled by default - * in order to improve compatibility and/or - * performance. - * \param [in] appName Application name - * \returns Default configuration for the app - */ - Config getAppConfig(const std::string& appName); - - /** - * \brief Retrieves user configuration - * - * Opens and parses the file \c dxvk.conf if it - * exists, or whatever file name is specified in - * the environment variable \c DXVK_CONFIG_FILE. - * \returns User configuration - */ - Config getUserConfig(); - -} \ No newline at end of file diff --git a/src/util/meson.build b/src/util/meson.build index 889ecceec..50583f23c 100644 --- a/src/util/meson.build +++ b/src/util/meson.build @@ -6,7 +6,6 @@ util_src = files([ 'com/com_private_data.cpp', 'config/config.cpp', - 'config/config_user.cpp', 'log/log.cpp', 'log/log_debug.cpp',