Repository: LunarG/VulkanTools
Pull request #2322: vkconfig: Improved generated layer documentation
Author: login: christophe-lunarg
Labels: name: bug
name: enhancement
name: P2
description: Has a workaround / Minor feature
name: Project - vkconfig
description: Issues related to vkconfig
name: OS - platform independent
description: The issue doesn't depend on the OS
Created: 2025-04-02T13:21:04Z | Merged: 2025-04-02T14:47:42Z

### Improvements:
- Clarify VK_EXT_layer_settings variable names in generated layer documentation
- Hide `advanced` settings from generated layer documentation, used only by layer developers

### Fixes:
- Fix broken generated layer doc links

![image](https://github.com/user-attachments/assets/196973ca-59cc-47ba-9957-68bb4c118144)
- When we click on the layer setting label, it jumps to the details layer setting below.
- When we click on `Variables Key`, it opens the general layer settings documentation https://vulkan.lunarg.com/doc/sdk/1.4.309.0/windows/layer_configuration.html

![image](https://github.com/user-attachments/assets/0276b58b-71f2-4b6c-98ff-8e45d1ffa6b1)
When we click on `Setting Variables`, it opens the general layer settings documentation https://vulkan.lunarg.com/doc/sdk/1.4.309.0/windows/layer_configuration.html



Diff:
diff --git a/vkconfig_core/doc.cpp b/vkconfig_core/doc.cpp
index ff74a2317b..cfa12787be 100644
--- a/vkconfig_core/doc.cpp
+++ b/vkconfig_core/doc.cpp
@@ -55,24 +55,14 @@ static void WriteSettingsOverviewHtml(std::string& text, const Layer& layer, con
     for (std::size_t i = 0, n = settings.size(); i < n; ++i) {
         const SettingMeta* setting = settings[i];
 
-        if (setting->type != SETTING_GROUP && setting->view != SETTING_VIEW_HIDDEN) {
+        if (setting->type != SETTING_GROUP && setting->view == SETTING_VIEW_STANDARD) {
             text += "<tr>\n";
             text += format("\t<td><a id=\"%s\"href=\"#%s-detailed\">%s</a></td>\n", setting->key.c_str(), setting->key.c_str(),
                            setting->label.c_str());
 
+            text += format("\t<td><span class=\"code\">%s</span></td>\n", setting->key.c_str());
             text += format("\t<td><span class=\"code\">%s</span></td>\n", GetToken(setting->type));
             text += format("\t<td><span class=\"code\">%s</span></td>\n", setting->Export(EXPORT_MODE_DOC).c_str());
-
-            text +=
-                format("\t<td><span class=\"code\">%s</span></td>\n", (GetLayerSettingPrefix(layer.key) + setting->key).c_str());
-
-            std::vector<std::string> envs = BuildEnvVariablesList(layer.key.c_str(), setting->key.c_str());
-            if (!setting->env.empty()) {
-                envs.push_back(setting->env);
-            }
-
-            text += format("\t<td><span class=\"code\">%s</span></td>\n", Merge(envs, "<BR/>").c_str());
-
             text += format("\t<td>%s</td>\n", BuildPlatformsHtml(setting->platform_flags).c_str());
             text += "</tr>\n";
         }
@@ -92,20 +82,12 @@ static void WriteSettingsOverviewMarkdown(std::string& text, const Layer& layer,
     for (std::size_t i = 0, n = settings.size(); i < n; ++i) {
         const SettingMeta* setting = settings[i];
 
-        if (setting->type != SETTING_GROUP && setting->view != SETTING_VIEW_HIDDEN) {
-            text += "|" + setting->label + "|" + GetToken(setting->type) + "|";
-
-            text += setting->Export(EXPORT_MODE_DOC) + "|";
-
-            text += GetLayerSettingPrefix(layer.key) + setting->key + "|";
-
-            std::vector<std::string> envs = BuildEnvVariablesList(layer.key.c_str(), setting->key.c_str());
-            if (!setting->env.empty()) {
-                envs.push_back(setting->env);
-            }
-            text += Merge(envs, ", ");
-
+        if (setting->type != SETTING_GROUP && setting->view == SETTING_VIEW_STANDARD) {
             text += "|";
+            text += setting->label + "|";
+            text += setting->key + "|";
+            text += GetToken(setting->type) + std::string("|");
+            text += setting->Export(EXPORT_MODE_DOC) + "|";
             text += BuildPlatformsMarkdown(setting->platform_flags) + "|\n";
         }
 
@@ -122,13 +104,9 @@ static void WriteSettingsOverviewMarkdown(std::string& text, const Layer& layer,
 
 static const std::string GetLayerSettingsDocURL(const Layer& layer) {
     if (layer.api_version >= Version(1, 3, 268)) {
-        return format("https://github.com/LunarG/VulkanTools/tree/sdk-%s.0/vkconfig#vulkan-layers-settings",
-                      layer.api_version.str().c_str());
-    } else if (layer.api_version > Version(1, 2, 182)) {
-        return format("https://github.com/LunarG/VulkanTools/tree/sdk-%s.0/vkconfig#vulkan-layers-settings",
-                      layer.api_version.str().c_str());
+        return format("https://vulkan.lunarg.com/doc/sdk/%s.0/windows/layer_configuration.html", layer.api_version.str().c_str());
     } else {
-        return "https://github.com/LunarG/VulkanTools/tree/main/vkconfig#vulkan-layers-settings";
+        return "https://vulkan.lunarg.com/doc/view/latest/windows/layer_configuration.html";
     }
 }
 
@@ -136,7 +114,7 @@ static void WriteSettingsDetailsHtml(std::string& text, const Layer& layer, cons
     for (std::size_t i = 0, n = settings.size(); i < n; ++i) {
         const SettingMeta* setting = settings[i];
 
-        if (setting->type != SETTING_GROUP && setting->view != SETTING_VIEW_HIDDEN) {
+        if (setting->type != SETTING_GROUP && setting->view == SETTING_VIEW_STANDARD) {
             if (setting->status == STATUS_STABLE) {
                 text += format("<h3><a id=\"%s-detailed\" href=\"#%s\">%s</a></h3>\n", setting->key.c_str(), setting->key.c_str(),
                                setting->label.c_str());
@@ -147,29 +125,26 @@ static void WriteSettingsDetailsHtml(std::string& text, const Layer& layer, cons
 
             text += format("\t<p>%s</p>\n", setting->description.c_str());
 
-            text += "<h4>Setting Properties:</h4>\n";
+            text += format("<h4><a href=\"%s\">Setting Variables:</a></h4>\n", GetLayerSettingsDocURL(layer).c_str());
             text += "<ul>\n";
-            text += format("\t<li><a href=\"%s\">vk_layer_settings.txt</a> Variable: <span class=\"code\">%s</span></li>\n",
-                           GetLayerSettingsDocURL(layer).c_str(), (GetLayerSettingPrefix(layer.key) + setting->key).c_str());
+            text += format("\t<li>VK_EXT_layer_settings variable: <span class=\"code\">%s</span></li>\n", setting->key.c_str());
+            text += format("\t<li>vk_layer_settings.txt variable: <span class=\"code\">%s</span></li>\n",
+                           (GetLayerSettingPrefix(layer.key) + setting->key).c_str());
 
             std::vector<std::string> envs = BuildEnvVariablesList(layer.key.c_str(), setting->key.c_str());
             if (!setting->env.empty()) {
                 envs.push_back(setting->env);
             }
             text +=
-                format("\t<li>Environment Variables: <BR/> <span class=\"code\">%s</span></li>\n", Merge(envs, "<BR/>").c_str());
-
-            text += format("\t<li>Platforms: %s</li>\n", BuildPlatformsHtml(setting->platform_flags).c_str());
-
-            if (setting->view != SETTING_VIEW_STANDARD) {
-                text += format("\t<li>Setting Level: %s</li>\n", GetToken(setting->view));
-            }
+                format("\t<li>Environment variables: <BR/> <span class=\"code\">%s</span></li>\n", Merge(envs, "<BR/>").c_str());
+            text += "</ul>\n";
 
-            text += format(
-                "\t<li>Setting Type: <span class=\"code\">%s</span></li>\n\t<li>Setting Default Value: <span "
-                "class=\"code\">%s</span></li>\n",
-                GetToken(setting->type), setting->Export(EXPORT_MODE_DOC).c_str());
+            text += "<h4>Setting Properties:</h4>\n";
+            text += "<ul>\n";
 
+            text += format("\t<li>Type: <span class=\"code\">%s</span></li>\n", GetToken(setting->type));
+            text += format("\t<li>Default Value: <span class=\"code\">%s</span></li>\n", setting->Export(EXPORT_MODE_DOC).c_str());
+            text += format("\t<li>Platforms: %s</li>\n", BuildPlatformsHtml(setting->platform_flags).c_str());
             text += "</ul>\n";
 
             if (IsEnum(setting->type) || IsFlags(setting->type)) {
@@ -187,7 +162,9 @@ static void WriteSettingsDetailsHtml(std::string& text, const Layer& layer, cons
                     for (std::size_t j = 0, o = setting_enum.enum_values.size(); j < o; ++j) {
                         const SettingEnumValue& value = setting_enum.enum_values[j];
 
-                        if (value.view == SETTING_VIEW_HIDDEN) continue;
+                        if (value.view != SETTING_VIEW_STANDARD) {
+                            continue;
+                        }
 
                         text += "<tr>\n";
                         text += format("\t<td>%s</td>\n", value.key.c_str());
@@ -217,7 +194,7 @@ static void WriteSettingsDetailsMarkdown(std::string& text, const Layer& layer,
     for (std::size_t i = 0, n = settings.size(); i < n; ++i) {
         const SettingMeta* setting = settings[i];
 
-        if (setting->type != SETTING_GROUP && setting->view != SETTING_VIEW_HIDDEN) {
+        if (setting->type != SETTING_GROUP && setting->view == SETTING_VIEW_STANDARD) {
             if (setting->status == STATUS_STABLE) {
                 text += "#### " + setting->label;
             } else {
@@ -227,23 +204,24 @@ static void WriteSettingsDetailsMarkdown(std::string& text, const Layer& layer,
 
             text += setting->description + "\n";
 
-            text += "##### Setting Properties:\n";
-            text += "- vk_layer_settings.txt Variable: " + GetLayerSettingPrefix(layer.key) + setting->key + "\n";
+            text += "##### Setting Variables:\n";
+            text += "- VK_EXT_layer_settings variable: " + setting->key + "\n";
+            text += "- vk_layer_settings.txt variable: " + GetLayerSettingPrefix(layer.key) + setting->key + "\n";
 
             std::vector<std::string> envs = BuildEnvVariablesList(layer.key.c_str(), setting->key.c_str());
             if (!setting->env.empty()) {
                 envs.push_back(setting->env);
             }
-            text += "- Environment Variables: " + Merge(envs, ", ") + "\n";
-
-            text += "- Platforms: " + BuildPlatformsMarkdown(setting->platform_flags) + "\n";
-
-            if (setting->view != SETTING_VIEW_STANDARD) {
-                text += format("- Setting Level: %s\n", GetToken(setting->view));
+            text += "- Environment variables:\n";
+            for (std::size_t i = 0, n = envs.size(); i < n; ++i) {
+                text += format("  - %s\n", envs[i].c_str());
             }
 
-            text += format("- Setting Type: %s\n- Setting Default Value: %s\n\n", GetToken(setting->type),
-                           setting->Export(EXPORT_MODE_DOC).c_str());
+            text += "##### Setting Properties:\n";
+            text += format("- Type: %s\n", GetToken(setting->type));
+            text += format("- Default Value: %s\n", setting->Export(EXPORT_MODE_DOC).c_str());
+            text += "- Platforms: " + BuildPlatformsMarkdown(setting->platform_flags) + "\n";
+            text += "\n";
 
             if (IsEnum(setting->type) || IsFlags(setting->type)) {
                 const SettingMetaEnumeration& setting_enum = static_cast<const SettingMetaEnumeration&>(*setting);
@@ -258,7 +236,9 @@ static void WriteSettingsDetailsMarkdown(std::string& text, const Layer& layer,
                     for (std::size_t j = 0, o = setting_enum.enum_values.size(); j < o; ++j) {
                         const SettingEnumValue& value = setting_enum.enum_values[j];
 
-                        if (value.view == SETTING_VIEW_HIDDEN) continue;
+                        if (value.view != SETTING_VIEW_STANDARD) {
+                            continue;
+                        }
 
                         text += "|" + value.key + "|" + value.label + "|";
                         if (value.description.empty()) {
@@ -353,10 +333,9 @@ bool ExportHtmlDoc(const Layer& layer, const std::string& path) {
     if (!layer.settings.empty()) {
         text += "<h2><a id=\"settings\">Layer Settings Overview</a></h2>\n";
         text += "<table><thead><tr>";
-        text += format(
-            "<th>Setting</th><th>Type</th><th>Default Value</th><th><a href=\"%s\">vk_layer_settings.txt</a> Variable</th>"
-            "<th>Environment Variable</th><th>Platforms</th>",
-            GetLayerSettingsDocURL(layer).c_str());
+        text +=
+            format("<th>Label</th><th><a href=\"%s\">Variables Key</a></th><th>Type</th><th>Default Value</th><th>Platforms</th>",
+                   GetLayerSettingsDocURL(layer).c_str());
         text += "</tr></thead><tbody>\n";
         WriteSettingsOverviewHtml(text, layer, layer.settings);
         text += "</tbody></table>\n";
@@ -425,6 +404,9 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
     text += (layer.binary_path.RelativePath().rfind("./", 0) == 0 ? layer.binary_path.RelativePath().substr(2)
                                                                   : layer.binary_path.RelativePath()) +
             "\n";
+    text += "- Variables:\n";
+    text += format("  - vk_layer_settings.txt namespace: %s\n", ToLowerCase(TrimPrefix(layer.key)).c_str());
+    text += format("  - Environment Variable prefix: VK_%s_\n", ToUpperCase(TrimPrefix(layer.key)).c_str());
 
     if (layer.platforms != 0) {
         text += "- Platforms: " + BuildPlatformsMarkdown(layer.platforms) + "\n";
@@ -442,9 +424,10 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
 
     if (!layer.settings.empty()) {
         text += "### Layer Settings Overview\n";
-        text += "|Setting|Type|Default Value|vk_layer_settings.txt Variable|Environment Variable|Platforms|\n";
-        text += "|---|---|---|---|---|---|\n";
+        text += "|Label|Variables Key|Type|Default Value|Platforms|\n";
+        text += "|---|---|---|---|---|\n";
         WriteSettingsOverviewMarkdown(text, layer, layer.settings);
+        text += "\n";
 
         text += "### Layer Settings Details\n";
         WriteSettingsDetailsMarkdown(text, layer, layer.settings);
@@ -456,7 +439,7 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
             const LayerPreset& preset = layer.presets[i];
 
             text += "#### " + preset.label + "\n";
-            text += preset.description + "\n";
+            text += preset.description + "\n\n";
             text += "##### Preset Setting Values:\n";
             for (std::size_t j = 0, o = preset.settings.size(); j < o; ++j) {
                 const SettingData* data = preset.settings[j];
@@ -464,6 +447,7 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
 
                 text += "- " + meta->label + ": " + data->Export(EXPORT_MODE_DOC).c_str() + "\n";
             }
+            text += "\n";
         }
     }
 
diff --git a/vkconfig_core/layer.cpp b/vkconfig_core/layer.cpp
index 7ad4e60514..7b91fe0f02 100644
--- a/vkconfig_core/layer.cpp
+++ b/vkconfig_core/layer.cpp
@@ -452,6 +452,8 @@ void Layer::AddSettingsSet(SettingMetaSet& settings, const SettingMeta* parent,
         SettingView view = SETTING_VIEW_STANDARD;
         if (json_setting.value("view") != QJsonValue::Undefined) {
             view = GetSettingView(ReadStringValue(json_setting, "view").c_str());
+        } else if (parent != nullptr) {
+            view = parent->view;
         }
         if (view == SETTING_VIEW_HIDDEN) {
             continue;
@@ -460,9 +462,7 @@ void Layer::AddSettingsSet(SettingMetaSet& settings, const SettingMeta* parent,
         SettingMeta* setting_meta = Instantiate(settings, key, type);
         setting_meta->platform_flags = parent == nullptr ? this->platforms : parent->platform_flags;
         setting_meta->status = parent == nullptr ? STATUS_STABLE : parent->status;
-        if (parent != nullptr) {
-            setting_meta->view = parent->view;
-        }
+        setting_meta->view = view;
 
         LoadMetaHeader(*setting_meta, json_setting);
         if (json_setting.value("env") != QJsonValue::Undefined) {
diff --git a/vkconfig_core/vulkan_util.cpp b/vkconfig_core/vulkan_util.cpp
index 9961aa738a..0f5417cb91 100644
--- a/vkconfig_core/vulkan_util.cpp
+++ b/vkconfig_core/vulkan_util.cpp
@@ -275,7 +275,7 @@ enum TrimMode {
     TRIM_LAST = TRIM_NAMESPACE,
 };
 
-static std::string TrimPrefix(const std::string &layer_key) {
+std::string TrimPrefix(const std::string &layer_key) {
     std::string key{};
     if (layer_key.find("VK_LAYER_") == 0) {
         std::size_t prefix = std::strlen("VK_LAYER_");
diff --git a/vkconfig_core/vulkan_util.h b/vkconfig_core/vulkan_util.h
index 7708cfb08d..3d330ffbb1 100644
--- a/vkconfig_core/vulkan_util.h
+++ b/vkconfig_core/vulkan_util.h
@@ -61,6 +61,7 @@ struct VulkanSystemInfo {
 
 VulkanSystemInfo BuildVulkanSystemInfo();
 
+std::string TrimPrefix(const std::string &layer_key);
 std::vector<std::string> BuildEnvVariablesList(const char *layer_key, const char *setting_key);
 
 const char *GetLabel(VkPhysicalDeviceType deviceType);
diff --git a/vkconfig_gui/CHANGELOG.md b/vkconfig_gui/CHANGELOG.md
index f6648562b9..d8e35ea8d8 100644
--- a/vkconfig_gui/CHANGELOG.md
+++ b/vkconfig_gui/CHANGELOG.md
@@ -11,10 +11,13 @@
 - Refactor layer version combobox
 - Clean up UI layout
 - Add button to remove missing layers
+- Clarify VK_EXT_layer_settings variable names in generated layer documentation
+- Hide `advanced` settings from generated layer documentation, used only by layer developers
 
 ### Fixes:
 - Fix layer settings all display with the layer development status
 - Fix reset to default when stay in system tray is checked
+- Fix broken generated layer doc links
 
 ## Vulkan Configurator 3.1.0 - March 2025
 [Vulkan SDK 1.4.309.0](https://github.com/LunarG/VulkanTools/tree/vulkan-sdk-1.4.309)


Reviews:
user: login: spencer-lunarg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T13:33:35Z
user: login: christophe-lunarg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T14:24:12Z
user: login: spencer-lunarg
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T14:33:55Z
user: login: spencer-lunarg
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-02T14:34:16Z

Review comments:
diff_hunk: @@ -442,7 +441,8 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
 
     if (!layer.settings.empty()) {
         text += "### Layer Settings Overview\n";
-        text += "|Setting|Type|Default Value|vk_layer_settings.txt Variable|Environment Variable|Platforms|\n";
+        text +=
+            "|Setting|Type|Default Value|vk_layer_settings.txt/VK_EXT_layer_settings Variable|Environment Variable|Platforms|\n";
path: vkconfig_core/doc.cpp
user: login: spencer-lunarg
body: The idea is we don't want `khronos_validation.fine_grained_locking` we just want `fine_grained_locking` for the `VK_EXT_layer_settings` name 
created_at: 2025-04-02T13:33:35Z
author_association: CONTRIBUTOR
diff_hunk: @@ -442,7 +441,8 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
 
     if (!layer.settings.empty()) {
         text += "### Layer Settings Overview\n";
-        text += "|Setting|Type|Default Value|vk_layer_settings.txt Variable|Environment Variable|Platforms|\n";
+        text +=
+            "|Setting|Type|Default Value|vk_layer_settings.txt/VK_EXT_layer_settings Variable|Environment Variable|Platforms|\n";
path: vkconfig_core/doc.cpp
user: login: christophe-lunarg
body: @spencer-lunarg see the PR description for a screenshot and to get an idea what it looks like
created_at: 2025-04-02T14:24:12Z
author_association: CONTRIBUTOR
diff_hunk: @@ -442,7 +441,8 @@ bool ExportMarkdownDoc(const Layer& layer, const std::string& path) {
 
     if (!layer.settings.empty()) {
         text += "### Layer Settings Overview\n";
-        text += "|Setting|Type|Default Value|vk_layer_settings.txt Variable|Environment Variable|Platforms|\n";
+        text +=
+            "|Setting|Type|Default Value|vk_layer_settings.txt/VK_EXT_layer_settings Variable|Environment Variable|Platforms|\n";
path: vkconfig_core/doc.cpp
user: login: spencer-lunarg
body: ok that looks nice
created_at: 2025-04-02T14:33:55Z
author_association: CONTRIBUTOR

PR comments:
user: login: ci-tester-lunarg
created_at: 2025-04-02T13:21:08Z
body: CI VulkanTools build # 4280 running.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T13:24:52Z
body: CI VulkanTools build # 4280 failed.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:24:56Z
body: CI VulkanTools build queued with queue ID 410807.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:25:01Z
body: CI VulkanTools build # 4281 running.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:30:42Z
body: CI VulkanTools build # 4281 passed.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:35:56Z
body: CI VulkanTools build queued with queue ID 410822.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:40:01Z
body: CI VulkanTools build # 4282 running.
author_association: NONE
user: login: ci-tester-lunarg
created_at: 2025-04-02T14:41:27Z
body: CI VulkanTools build # 4282 failed.
author_association: NONE