Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
180 changes: 180 additions & 0 deletions vkconfig_core/configurator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,186 @@ bool Configurator::WriteLoaderSettings(OverrideArea override_area, const Path& l
}
}

bool Configurator::Export(ExportEnvMode mode, const Path& export_path) const {
const char* COMMENT = mode == EXPORT_ENV_BASH ? "#! " : ":: ";
const char* EXPORT = mode == EXPORT_ENV_BASH ? "export " : "set ";

QFile file(export_path.AbsolutePath().c_str());

const bool result_layers_file = file.open(QIODevice::WriteOnly | QIODevice::Text);
if (!result_layers_file) {
return false;
}

bool has_missing_layers = false;
const Configuration* configuration = this->GetActiveConfiguration();

QTextStream stream(&file);

stream << COMMENT << "Loader Settings:\n";

const std::vector<std::string>& stderr_log = GetLogTokens(configuration->loader_log_messages_flags);
const std::string stderr_logs = Merge(stderr_log, ",");

if (configuration->override_loader) {
stream << EXPORT << "VK_LOADER_DEBUG=" << stderr_logs.c_str() << "\n";
}
if (configuration->override_layers) {
stream << COMMENT;
stream << "For now, the Vulkan Loader doesn't fully support the same behavior with environment variables than what's "
"supported with Vulkan Configurator...\n";
stream << COMMENT;
stream << "The Vulkan Loader doesn't support fully ordering layers with environment variables.\n";
stream << EXPORT << "VK_LOADER_LAYERS_ENABLE=";

std::vector<std::string> layer_list;
for (std::size_t i = 0, n = configuration->parameters.size(); i < n; ++i) {
const Parameter& parameter = configuration->parameters[i];
if (parameter.control != LAYER_CONTROL_ON) {
continue;
}
layer_list.push_back(parameter.key);
}
stream << Merge(layer_list, ",").c_str();
stream << "\n";
}

stream << "\n";

stream << COMMENT << "Layers Settings:\n";

// Loop through all the layers
for (std::size_t j = 0, n = configuration->parameters.size(); j < n; ++j) {
const Parameter& parameter = configuration->parameters[j];
if (!parameter.override_settings) {
continue;
}

if (!(parameter.platform_flags & (1 << VKC_PLATFORM))) {
continue;
}

if (parameter.builtin == LAYER_BUILTIN_UNORDERED) {
continue;
}

if (parameter.control == LAYER_CONTROL_DISCARD || parameter.control == LAYER_CONTROL_OFF) {
continue;
}

const Layer* layer = this->layers.Find(parameter.key.c_str(), parameter.api_version);
if (layer == nullptr) {
if (parameter.control == LAYER_CONTROL_ON) {
has_missing_layers = true;
fprintf(stderr,
"vkconfig: [ERROR] `%s` layer is set to `%s` in `%s` loader configuration but missing and being "
"ignored\n",
parameter.key.c_str(), ::GetLabel(parameter.control), configuration->key.c_str());
} else {
fprintf(stderr,
"vkconfig: [WARNING] `%s` layer is set to `%s` in `%s` loader configuration but missing and being "
"ignored\n",
parameter.key.c_str(), ::GetLabel(parameter.control), configuration->key.c_str());
}
continue;
}

stream << "\n";
stream << COMMENT << layer->key.c_str() << " " << layer->api_version.str().c_str() << "\n\n";

std::string lc_layer_name = GetLayerSettingPrefix(layer->key);

for (std::size_t i = 0, m = parameter.settings.size(); i < m; ++i) {
const SettingData* setting_data = parameter.settings[i];

// Skip groups - they aren't settings, so not relevant in this output
if (setting_data->type == SETTING_GROUP) {
continue;
}

// Skip missing settings
const SettingMeta* meta = FindSetting(layer->settings, setting_data->key.c_str());
if (meta == nullptr) {
continue;
}

// Skip overriden settings
if (::CheckSettingOverridden(*meta)) {
continue;
}

stream << COMMENT << meta->label.c_str() << "\n";
stream << COMMENT << "=====================\n";
stream << COMMENT << meta->key.c_str();

if (meta->status != STATUS_STABLE) {
stream << format(" (%s)", GetToken(meta->status)).c_str();
}

stream << "\n";

// Break up description into smaller words
std::string description = meta->description;
std::vector<std::string> words;
std::size_t pos;
while ((pos = description.find(" ")) != std::string::npos) {
words.push_back(description.substr(0, pos));
description.erase(0, pos + 1);
}
if (description.size() > 0) words.push_back(description);
if (words.size() > 0) {
stream << COMMENT;
std::size_t nchars = std::strlen(COMMENT);
for (auto word : words) {
if (word.size() + nchars > 80) {
stream << "\n";
stream << COMMENT;
nchars = std::strlen(COMMENT);
}
stream << " " << word.c_str();
nchars += (word.size() + 1);
}
}
stream << "\n";

// If feature has unmet dependency, output it but comment it out
if (::CheckDependence(*meta, parameter.settings) != SETTING_DEPENDENCE_ENABLE) {
stream << COMMENT;
}

if (meta->status == STATUS_DEPRECATED && !meta->deprecated_by_key.empty()) {
const SettingMeta* replaced_setting = FindSetting(layer->settings, meta->deprecated_by_key.c_str());

stream << COMMENT;
stream << format("This setting was deprecated and replaced by '%s' (%s) setting.\n",
replaced_setting->label.c_str(), replaced_setting->key.c_str())
.c_str();
}

std::vector<std::string> data = ::BuildEnvVariablesList(layer->key.c_str(), setting_data->key.c_str(), false);
const bool need_wordaround = mode == EXPORT_ENV_BASH && setting_data->key == "force_device_name";

stream << EXPORT << data[0].c_str() << "=";

if (need_wordaround) {
stream << "\"";
}

stream << setting_data->Export(EXPORT_MODE_OVERRIDE).c_str();

if (need_wordaround) {
stream << "\"";
}

stream << "\n\n";
}
}

file.close();

return true;
}

// Create and write vk_layer_settings.txt file
bool Configurator::WriteLayersSettings(OverrideArea override_area, const Path& layers_settings_path) {
if (override_area & OVERRIDE_AREA_LAYERS_SETTINGS_BIT) {
Expand Down
3 changes: 3 additions & 0 deletions vkconfig_core/configurator.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ enum EnabledUI {
ENABLE_UI_SETTINGS,
};

enum ExportEnvMode { EXPORT_ENV_BASH = 0, EXPORT_ENV_CMD };

class Configurator {
public:
struct LayersSettings {
Expand Down Expand Up @@ -99,6 +101,7 @@ class Configurator {

bool WriteLayersSettings(OverrideArea override_area, const Path& layers_settings_path);
bool WriteLoaderSettings(OverrideArea override_area, const Path& loader_settings_path);
bool Export(ExportEnvMode mode, const Path& export_path) const;

void Set(HideMessageType type);
bool Get(HideMessageType type) const;
Expand Down
1 change: 1 addition & 0 deletions vkconfig_gui/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
### Features:
- Add support for layer-defined messages
- Add support for external `vk_layer_settings.txt` files
- Add environment variables export of loader configurations

### Improvements:
- Improved layer settings documentation
Expand Down
56 changes: 56 additions & 0 deletions vkconfig_gui/tab_configurations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -562,6 +562,14 @@ bool TabConfigurations::EventFilter(QObject *target, QEvent *event) {
action_export_settings->setEnabled(item != nullptr);
menu.addAction(action_export_settings);

QAction *action_export_env_variables_bash_script = new QAction("Export the Bash script...", nullptr);
action_export_env_variables_bash_script->setEnabled(item != nullptr);
menu.addAction(action_export_env_variables_bash_script);

QAction *action_export_env_variables_cmd_script = new QAction("Export the Command Prompt script...", nullptr);
action_export_env_variables_cmd_script->setEnabled(item != nullptr);
menu.addAction(action_export_env_variables_cmd_script);

menu.addSeparator();

QAction *action_external_settings = new QAction("Use External Layers Settings file...", nullptr);
Expand All @@ -587,6 +595,10 @@ bool TabConfigurations::EventFilter(QObject *target, QEvent *event) {
this->OnContextMenuResetAllClicked(item);
} else if (action == action_export_config) {
this->OnContextMenuExportConfigsClicked(item);
} else if (action == action_export_env_variables_bash_script) {
this->OnContextMenuExportEnvVariablesBashClicked(item);
} else if (action == action_export_env_variables_cmd_script) {
this->OnContextMenuExportEnvVariablesCMDClicked(item);
} else if (action == action_export_settings) {
this->OnContextMenuExportSettingsClicked(item);
} else if (action == action_external_settings) {
Expand Down Expand Up @@ -1016,6 +1028,50 @@ void TabConfigurations::OnContextMenuExportConfigsClicked(ListItem *item) {
}
}

void TabConfigurations::OnContextMenuExportEnvVariablesBashClicked(ListItem *item) {
assert(item);
Configurator &configurator = Configurator::Get();

const Path path_export = configurator.configurations.last_path_export_config.RelativePath() + "/" + item->key + ".sh";
const QString &selected_path = QFileDialog::getSaveFileName(&this->window, "Export Environment Variables bash script",
path_export.AbsolutePath().c_str(), "Shell Script(*.sh)");

const bool result = configurator.Export(EXPORT_ENV_BASH, selected_path.toStdString());

if (!result) {
QMessageBox msg;
msg.setIcon(QMessageBox::Critical);
msg.setWindowTitle("Exporting of a file failed...");
msg.setText(format("Couldn't be create '%s' file.", selected_path.toStdString().c_str()).c_str());
msg.exec();
} else {
Path path(selected_path.toStdString());
QDesktopServices::openUrl(QUrl::fromLocalFile(path.AbsoluteDir().c_str()));
}
}

void TabConfigurations::OnContextMenuExportEnvVariablesCMDClicked(ListItem *item) {
assert(item);
Configurator &configurator = Configurator::Get();

const Path path_export = configurator.configurations.last_path_export_config.RelativePath() + "/" + item->key + ".bat";
const QString &selected_path = QFileDialog::getSaveFileName(&this->window, "Export Environment Variables command prompt script",
path_export.AbsolutePath().c_str(), "Command Prompt Script(*.bat)");

const bool result = configurator.Export(EXPORT_ENV_CMD, selected_path.toStdString());

if (!result) {
QMessageBox msg;
msg.setIcon(QMessageBox::Critical);
msg.setWindowTitle("Exporting of a file failed...");
msg.setText(format("Couldn't be create '%s' file.", selected_path.toStdString().c_str()).c_str());
msg.exec();
} else {
Path path(selected_path.toStdString());
QDesktopServices::openUrl(QUrl::fromLocalFile(path.AbsoluteDir().c_str()));
}
}

void TabConfigurations::OnContextMenuExportSettingsClicked(ListItem *item) {
assert(item);

Expand Down
2 changes: 2 additions & 0 deletions vkconfig_gui/tab_configurations.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class TabConfigurations : public Tab {
void OnContextMenuResetOneClicked(ListItem *item);
void OnContextMenuResetAllClicked(ListItem *item);
void OnContextMenuExportConfigsClicked(ListItem *item);
void OnContextMenuExportEnvVariablesBashClicked(ListItem *item);
void OnContextMenuExportEnvVariablesCMDClicked(ListItem *item);
void OnContextMenuExportSettingsClicked(ListItem *item);

void UpdatePerExecutableConfigurations();
Expand Down