Merge commit 'd2de4ac0a28766c6fb10968fdcc4d75566eef8d7' into merge-vulkan-1.1.108

Change-Id: I89494ed40c0f7b16eca3eee6dd4c2287b53f4c29
diff --git a/.appveyor.yml b/.appveyor.yml
index 281eb2e..0b82eff 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -25,30 +25,14 @@
 before_build:
   - "SET PATH=C:\\Python35;C:\\Python35\\Scripts;%PATH%"
   - echo Starting build for %APPVEYOR_REPO_NAME% in %APPVEYOR_BUILD_FOLDER%
-  # Build Vulkan-Headers
-  - echo Building Vulkan-Headers for %PLATFORM% %CONFIGURATION%
-  - cd %APPVEYOR_BUILD_FOLDER%
-  - git clone https://github.com/KhronosGroup/Vulkan-Headers.git
-  - cd Vulkan-Headers
-  - mkdir build
-  - cd build
-  - cmake -A %PLATFORM% -DCMAKE_INSTALL_PREFIX=install ..
-  - cmake --build . --config %CONFIGURATION% --target install -- /maxcpucount
-  # Build Vulkan-Loader
-  - echo Building Vulkan-Loader for %PLATFORM% %CONFIGURATION%
-  - cd %APPVEYOR_BUILD_FOLDER%
-  - git clone https://github.com/KhronosGroup/Vulkan-Loader.git
-  - cd Vulkan-Loader
-  - mkdir build
-  - cd build
-  - cmake -A %PLATFORM% -DVULKAN_HEADERS_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER%/Vulkan-Headers/build/install -DCMAKE_INSTALL_PREFIX=install ..
-  - cmake --build . --config %CONFIGURATION% --target install -- /maxcpucount
+  - cmake --version
   # Generate build files using CMake for the build step.
   - echo Generating Vulkan-Tools CMake files for %PLATFORM% %CONFIGURATION%
   - cd %APPVEYOR_BUILD_FOLDER%
   - mkdir build
   - cd build
-  - cmake -A %PLATFORM% -DVULKAN_HEADERS_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER%/Vulkan-Headers/build/install -DVULKAN_LOADER_INSTALL_DIR=%APPVEYOR_BUILD_FOLDER%/Vulkan-Loader/build/install ..
+  - python %APPVEYOR_BUILD_FOLDER%/scripts/update_deps.py --arch=%PLATFORM% --config=%CONFIGURATION% --dir=%APPVEYOR_BUILD_FOLDER%/external
+  - cmake -A %PLATFORM% -C %APPVEYOR_BUILD_FOLDER%/external/helper.cmake ..
   - echo Building platform=%PLATFORM% configuration=%CONFIGURATION%
 
 platform:
diff --git a/.gn b/.gn
new file mode 100644
index 0000000..e190259
--- /dev/null
+++ b/.gn
@@ -0,0 +1,22 @@
+# Copyright (C) 2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+buildconfig = "//build/config/BUILDCONFIG.gn"
+secondary_source = "//build-gn/secondary/"
+
+default_args = {
+    clang_use_chrome_plugins = false
+    use_custom_libcxx = false
+}
+
diff --git a/.travis.yml b/.travis.yml
index ea522fb..6e09f66 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -10,6 +10,7 @@
   fast_finish: true
   allow_failures:
     - env: CHECK_COMMIT_FORMAT=ON
+    - env: VULKAN_BUILD_TARGET=GN
   include:
     # Android build.
     - os: linux
@@ -27,6 +28,9 @@
     - os: linux
       compiler: clang
       env: VULKAN_BUILD_TARGET=LINUX
+    # Linux GN debug build
+    - os: linux
+      env: VULKAN_BUILD_TARGET=GN
     # Check for proper clang formatting in the pull request.
     - env: CHECK_FORMAT=ON
     # Check for proper commit message formatting for commits in PR
@@ -42,10 +46,10 @@
 before_install:
   - set -e
   - |
-    if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]]; then
+    if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]] || [[ "$VULKAN_BUILD_TARGET" == "GN" ]]; then
       # Install the appropriate Linux packages.
       sudo apt-get -qq update
-      sudo apt-get -y install libxkbcommon-dev libwayland-dev libmirclient-dev libxrandr-dev libx11-xcb-dev
+      sudo apt-get -y install libxkbcommon-dev libwayland-dev libmirclient-dev libxrandr-dev libx11-xcb-dev python-pathlib
     fi
   - |
     if [[ "$VULKAN_BUILD_TARGET" == "ANDROID" ]]; then
@@ -69,37 +73,15 @@
 
 script:
   - set -e
-  - |
-    if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]]; then
-      # Build Vulkan-Headers
-      cd ${TRAVIS_BUILD_DIR}
-      git clone https://github.com/KhronosGroup/Vulkan-Headers.git
-      cd Vulkan-Headers
-      mkdir build
-      cd build
-      cmake -DCMAKE_INSTALL_PREFIX=install ..
-      make -j $core_count install
-      cd ${TRAVIS_BUILD_DIR}
-    fi
-  - |
-    if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]]; then
-      # Build Vulkan-Loader for Vulkan-Tools
-      cd ${TRAVIS_BUILD_DIR}
-      git clone https://github.com/KhronosGroup/Vulkan-Loader.git
-      cd Vulkan-Loader
-      mkdir build
-      cd build
-      cmake -DCMAKE_BUILD_TYPE=Debug -DVULKAN_HEADERS_INSTALL_DIR=${TRAVIS_BUILD_DIR}/Vulkan-Headers/build/install -DCMAKE_INSTALL_PREFIX=install ..
-      make -j $core_count install
-      cd ${TRAVIS_BUILD_DIR}
-    fi
+  - cmake --version
   - |
     if [[ "$VULKAN_BUILD_TARGET" == "LINUX" ]]; then
       # Build Vulkan-Tools
       cd ${TRAVIS_BUILD_DIR}
       mkdir build
       cd build
-      cmake -DCMAKE_BUILD_TYPE=Debug -DVULKAN_HEADERS_INSTALL_DIR=${TRAVIS_BUILD_DIR}/Vulkan-Headers/build/install -DVULKAN_LOADER_INSTALL_DIR=${TRAVIS_BUILD_DIR}/Vulkan-Loader/build/install ..
+      python ${TRAVIS_BUILD_DIR}/scripts/update_deps.py --config=Debug --dir=${TRAVIS_BUILD_DIR}/external
+      cmake -C${TRAVIS_BUILD_DIR}/external/helper.cmake -DCMAKE_BUILD_TYPE=Debug ..
       make -j $core_count
       cd ${TRAVIS_BUILD_DIR}
     fi
@@ -122,6 +104,14 @@
       popd
     fi
   - |
+    if [[ "$VULKAN_BUILD_TARGET" == "GN" ]]; then
+      git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git depot_tools
+      export PATH=$PATH:$PWD/depot_tools
+      ./build-gn/update_deps.sh
+      gn gen out/Debug
+      ninja -C out/Debug
+    fi
+  - |
     if [[ "$CHECK_FORMAT" == "ON" ]]; then
       if [[ "$TRAVIS_PULL_REQUEST" != "false" ]]; then
         # Run the clang format check only for pull request builds because the
diff --git a/BUILD.gn b/BUILD.gn
new file mode 100644
index 0000000..c6cc155
--- /dev/null
+++ b/BUILD.gn
@@ -0,0 +1,206 @@
+# Copyright (C) 2018-2019 The ANGLE Project Authors.
+# Copyright (C) 2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+import("//build_overrides/vulkan_tools.gni")
+
+vulkan_registry_script_files = [
+  "$vulkan_headers_dir/registry/cgenerator.py",
+  "$vulkan_headers_dir/registry/conventions.py",
+  "$vulkan_headers_dir/registry/generator.py",
+  "$vulkan_headers_dir/registry/reg.py",
+  "$vulkan_headers_dir/registry/vkconventions.py",
+  "$vulkan_headers_dir/registry/vk.xml",
+]
+
+# Vulkan-tools isn't ported to Fuchsia yet.
+# TODO(spang): Port mock ICD to Fuchsia.
+assert(!is_fuchsia)
+
+vulkan_undefine_configs = []
+if (is_win) {
+  vulkan_undefine_configs += [
+    "//build/config/win:nominmax",
+    "//build/config/win:unicode",
+  ]
+}
+
+raw_vulkan_icd_dir = rebase_path("icd", root_build_dir)
+raw_vulkan_headers_dir = rebase_path("$vulkan_headers_dir", root_build_dir)
+
+vulkan_gen_dir = "$target_gen_dir/$vulkan_gen_subdir"
+raw_vulkan_gen_dir = rebase_path(vulkan_gen_dir, root_build_dir)
+
+vulkan_data_dir = "$root_out_dir/$vulkan_data_subdir"
+raw_vulkan_data_dir = rebase_path(vulkan_data_dir, root_build_dir)
+
+# Vulkan helper scripts
+# ---------------------
+
+helper_script_and_deps = [
+  [
+    "vulkan_gen_typemap_helper",
+    "vk_typemap_helper.h",
+    "vulkan_tools_helper_file_generator.py",
+  ],
+  [
+    "vulkan_mock_icd_cpp",
+    "mock_icd.cpp",
+    "mock_icd_generator.py",
+  ],
+  [
+    "vulkan_mock_icd_h",
+    "mock_icd.h",
+    "mock_icd_generator.py",
+  ],
+]
+
+# Python scripts needed for codegen, copy them to a temp dir
+# so that all dependencies are together
+copy("python_gen_deps") {
+  sources = vulkan_registry_script_files + [
+              "scripts/common_codegen.py",
+              "scripts/kvt_genvk.py",
+              "scripts/mock_icd_generator.py",
+              "scripts/vulkan_tools_helper_file_generator.py",
+            ]
+  outputs = [
+    "$vulkan_gen_dir/{{source_file_part}}",
+  ]
+}
+
+foreach(script_and_dep, helper_script_and_deps) {
+  target_name = script_and_dep[0]
+  file = script_and_dep[1]
+  dep = script_and_dep[2]
+  target("action", target_name) {
+    public_deps = [
+      ":python_gen_deps",
+    ]
+    script = "$vulkan_gen_dir/kvt_genvk.py"
+    inputs = [
+      "$vulkan_gen_dir/$dep",
+      "$vulkan_gen_dir/common_codegen.py",
+    ]
+    outputs = [
+      "$vulkan_gen_dir/$file",
+    ]
+    args = [
+      "-o",
+      raw_vulkan_gen_dir,
+      "-registry",
+      "$raw_vulkan_headers_dir/registry/vk.xml",
+      "-scripts",
+      "$raw_vulkan_headers_dir/registry",
+      "$file",
+      "-quiet",
+    ]
+  }
+}
+
+config("vulkan_generated_files_config") {
+  include_dirs = [ vulkan_gen_dir ]
+}
+
+group("vulkan_generate_helper_files") {
+  public_deps = [
+    "$vulkan_headers_dir:vulkan_headers",
+  ]
+  public_configs = [ ":vulkan_generated_files_config" ]
+  foreach(script_and_dep, helper_script_and_deps) {
+    target_name = script_and_dep[0]
+    public_deps += [ ":$target_name" ]
+  }
+}
+
+config("vulkan_internal_config") {
+  defines = [ "VULKAN_NON_CMAKE_BUILD" ]
+  if (is_clang || !is_win) {
+    cflags = [ "-Wno-unused-function" ]
+  }
+  if (is_linux) {
+    defines += [
+      "SYSCONFDIR=\"/etc\"",
+      "FALLBACK_CONFIG_DIRS=\"/etc/xdg\"",
+      "FALLBACK_DATA_DIRS=\"/usr/local/share:/usr/share\"",
+    ]
+  }
+}
+
+# Copy icd header to gen dir
+copy("icd_header_dep") {
+  sources = [
+    "$vulkan_headers_dir/include/vulkan/vk_icd.h",
+  ]
+  outputs = [
+    "$vulkan_gen_dir/vk_icd.h",
+  ]
+}
+
+if (!is_android) {
+  # Vulkan Mock ICD
+  # ---------------
+  group("vulkan_generate_mock_icd_files") {
+    public_deps = [
+      ":icd_header_dep",
+      ":vulkan_generate_helper_files",
+      ":vulkan_mock_icd_cpp",
+      ":vulkan_mock_icd_h",
+    ]
+  }
+
+  mock_icd_sources = [
+    "$vulkan_gen_dir/mock_icd.cpp",
+    "$vulkan_gen_dir/mock_icd.h",
+  ]
+
+  shared_library("VkICD_mock_icd") {
+    configs -= vulkan_undefine_configs
+    deps = [
+      ":vulkan_generate_mock_icd_files",
+    ]
+    data_deps = [
+      ":vulkan_gen_icd_json_file",
+    ]
+    sources = mock_icd_sources
+    if (is_win) {
+      sources += [ "icd/VkICD_mock_icd.def" ]
+    }
+    configs -= [ "//build/config/compiler:chromium_code" ]
+    configs += [ "//build/config/compiler:no_chromium_code" ]
+  }
+
+  action("vulkan_gen_icd_json_file") {
+    script = "build-gn/generate_vulkan_layers_json.py"
+    sources = [
+      "$vulkan_headers_dir/include/vulkan/vulkan_core.h",
+    ]
+    args = [ "--icd" ]
+    if (is_win) {
+      sources += [ "icd/windows/VkICD_mock_icd.json" ]
+      args += [ "$raw_vulkan_icd_dir/windows" ]
+    }
+    if (is_linux) {
+      sources += [ "icd/linux/VkICD_mock_icd.json" ]
+      args += [ "$raw_vulkan_icd_dir/linux" ]
+    }
+
+    # The layer JSON files are part of the necessary data deps.
+    outputs = [
+      "$vulkan_data_dir/VkICD_mock_icd.json",
+    ]
+    data = outputs
+    args += [ raw_vulkan_data_dir ] + rebase_path(sources, root_build_dir)
+  }
+}
diff --git a/BUILD.md b/BUILD.md
index dc33fa6..9b6aaba 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -197,7 +197,7 @@
     - [2017](https://www.visualstudio.com/vs/downloads/)
   - The Community Edition of each of the above versions is sufficient, as
     well as any more capable edition.
-- [CMake](http://www.cmake.org/download/) (Version 2.8.11 or better)
+- CMake: Continuous integration tools use [CMake 3.12.2](https://github.com/Kitware/CMake/releases/tag/v3.12.2) for Windows
   - Use the installer option to add CMake to the system PATH
 - Git Client Support
   - [Git for Windows](http://git-scm.com/download/win) is a popular solution
@@ -344,6 +344,8 @@
 although earlier versions may work. It should be straightforward to adapt this
 repository to other Linux distributions.
 
+The continuous integration tools use [CMake 3.12.4](https://github.com/Kitware/CMake/releases/tag/v3.12.4) for Linux
+
 #### Required Package List
 
     sudo apt-get install git cmake build-essential libx11-xcb-dev \
@@ -686,6 +688,8 @@
 
 Tested on OSX version 10.12.6
 
+The continuous integration tools use [CMake 3.11.3](https://github.com/Kitware/CMake/releases/tag/v3.11.3) for MacOS
+
 Setup Homebrew and components
 
 - Follow instructions on [brew.sh](http://brew.sh) to get Homebrew installed.
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index fab01a8..805528c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -23,6 +23,9 @@
   creating a branch with your commits, and then [submitting a pull request](https://help.github.com/articles/using-pull-requests/).
 * Please read and adhere to the style and process [guidelines ](#coding-conventions-and-formatting) enumerated below.
 * Please base your fixes on the master branch.  SDK branches are generally not updated except for critical fixes needed to repair an SDK release.
+* The resulting Pull Request will be assigned to a repository maintainer. It is the maintainer's responsibility to ensure the Pull Request
+  passes the Google/LunarG internal CI processes. Once the Pull Request has been approved and is passing internal CI, a repository maintainer
+  will merge the PR.
 
 
 #### **Coding Conventions and Formatting**
@@ -72,7 +75,9 @@
 >        vkcube --validate
 * In the `vulkaninfo` directory, run:
 >        vulkaninfo
-
+* If you are adding or changing JSON output, please read
+  [Validating vulkaninfo JSON output](https://github.com/KhronosGroup/Vulkan-Tools/blob/master/vulkaninfo/json_validation_process.md).
+  **Note:** When adding new output to vulkaninfo, do NOT add JSON output unless the formmatting is defined by a schema.
 * Run tests that explicitly exercise your changes.
 * Feel free to subject your code changes to other tests as well!
 
diff --git a/GOVERNANCE.md b/GOVERNANCE.md
index a8e7855..60fc12c 100644
--- a/GOVERNANCE.md
+++ b/GOVERNANCE.md
@@ -1,10 +1,9 @@
-## Vulkan Loader and Validation Layers Repository Management
+## Khronos Group Vulkan-Tools Repository Management
 
 # **Open Source Project – Objectives**
 
-* Alignment with the Vulkan Specification
-  - The goal is for tool and utility behavior to assist in enforcing the vulkan specification on applications. Questions on specification
-interpretations may require consulting with the Khronos Vulkan Workgroup for resolution
+* Assist Vulkan Users
+  - The goal is for tool and utility behavior to assist in the development of vulkan applications.
     - [Core Specification](https://www.khronos.org/registry/vulkan/specs/1.0/html/vkspec.html)
     - [Header Files](https://www.khronos.org/registry/vulkan/#headers)
     - [SDK Resources](https://vulkan.lunarg.com)
@@ -14,7 +13,7 @@
 * Cross Platform Compatibility
   - Google and LunarG collaboration:
     - Google: Monitor for Android
-    - LunarG: Monitor for desktop (Windows and Linux)
+    - LunarG: Monitor for desktop (Windows, Linux, and MacOS)
     - Continuous Integration: HW test farms operated by Google and LunarG monitor various hardware/software platforms
 * Repo Quality
   - Repo remains in healthy state with all tests passing and good-quality, consistent codebase
@@ -36,8 +35,7 @@
   - Is a point-of-contact for project-related questions
 
 The technical project leads for this repository are:
-* **Mark Lobodzinski** [mark@lunarg.com](mailto:mark@lunarg.com)
-* **Tobin Ehlis** [tobine@google.com](mailto:tobine@google.com)
+* **Jeremy Kniager** [jeremyk@lunarg.com](mailto:jeremyk@lunarg.com)
 
 # **Acceptance Criteria and Process**
   - All source code to include Khronos copyright and license (Apache 2.0).
diff --git a/build-android/vulkan-headers_revision_android b/build-android/vulkan-headers_revision_android
index 88920af..54f9e77 100644
--- a/build-android/vulkan-headers_revision_android
+++ b/build-android/vulkan-headers_revision_android
@@ -1 +1 @@
-v1.1.102
+v1.1.108
diff --git a/build-gn/DEPS b/build-gn/DEPS
new file mode 100644
index 0000000..81cca43
--- /dev/null
+++ b/build-gn/DEPS
@@ -0,0 +1,57 @@
+vars = {
+  'chromium_git': 'https://chromium.googlesource.com',
+}
+
+deps = {
+
+  './build': {
+    'url': '{chromium_git}/chromium/src/build.git@a660b0b9174e3a808f620222017566e8d1b2669b',
+  },
+
+  './buildtools': {
+    'url': '{chromium_git}/chromium/src/buildtools.git@459baaf66bee809f6eb288e0215cf524f4d2429a',
+  },
+
+  './testing': {
+    'url': '{chromium_git}/chromium/src/testing@083d633e752e7a57cbe62a468a06e51e28c49ee9',
+  },
+
+  './tools/clang': {
+    'url': '{chromium_git}/chromium/src/tools/clang.git@3114fbc11f9644c54dd0a4cdbfa867bac50ff983',
+  },
+
+}
+
+hooks = [
+  # Pull clang-format binaries using checked-in hashes.
+  {
+    'name': 'clang_format_linux',
+    'pattern': '.',
+    'condition': 'host_os == "linux"',
+    'action': [ 'download_from_google_storage',
+                '--no_resume',
+                '--platform=linux*',
+                '--no_auth',
+                '--bucket', 'chromium-clang-format',
+                '-s', './buildtools/linux64/clang-format.sha1',
+    ],
+  },
+  {
+    'name': 'sysroot_x64',
+    'pattern': '.',
+    'condition': 'checkout_linux and checkout_x64',
+    'action': ['python', './build/linux/sysroot_scripts/install-sysroot.py',
+               '--arch=x64'],
+  },
+  {
+    # Note: On Win, this should run after win_toolchain, as it may use it.
+    'name': 'clang',
+    'pattern': '.',
+    'action': ['python', './tools/clang/scripts/update.py'],
+  },
+]
+
+recursedeps = [
+  # buildtools provides clang_format.
+  './buildtools',
+]
diff --git a/build-gn/generate_vulkan_layers_json.py b/build-gn/generate_vulkan_layers_json.py
new file mode 100755
index 0000000..2999cd8
--- /dev/null
+++ b/build-gn/generate_vulkan_layers_json.py
@@ -0,0 +1,126 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2016 The ANGLE Project Authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+"""Generate copies of the Vulkan layers JSON files, with no paths, forcing
+Vulkan to use the default search path to look for layers."""
+
+from __future__ import print_function
+
+import argparse
+import glob
+import json
+import os
+import platform
+import sys
+
+
+def glob_slash(dirname):
+    """Like regular glob but replaces \ with / in returned paths."""
+    return [s.replace('\\', '/') for s in glob.glob(dirname)]
+
+
+def main():
+    parser = argparse.ArgumentParser(description=__doc__)
+    parser.add_argument('--icd', action='store_true')
+    parser.add_argument('source_dir')
+    parser.add_argument('target_dir')
+    parser.add_argument('version_header', help='path to vulkan_core.h')
+    parser.add_argument('json_files', nargs='*')
+    args = parser.parse_args()
+
+    source_dir = args.source_dir
+    target_dir = args.target_dir
+
+    json_files = [j for j in args.json_files if j.endswith('.json')]
+    json_in_files = [j for j in args.json_files if j.endswith('.json.in')]
+
+    data_key = 'ICD' if args.icd else 'layer'
+
+    if not os.path.isdir(source_dir):
+        print(source_dir + ' is not a directory.', file=sys.stderr)
+        return 1
+
+    if not os.path.exists(target_dir):
+        os.makedirs(target_dir)
+
+    # Copy the *.json files from source dir to target dir
+    if (set(glob_slash(os.path.join(source_dir, '*.json'))) != set(json_files)):
+        print(glob.glob(os.path.join(source_dir, '*.json')))
+        print('.json list in gn file is out-of-date', file=sys.stderr)
+        return 1
+
+    for json_fname in json_files:
+        if not json_fname.endswith('.json'):
+            continue
+        with open(json_fname) as infile:
+            data = json.load(infile)
+
+        # Update the path.
+        if not data_key in data:
+            raise Exception(
+                "Could not find '%s' key in %s" % (data_key, json_fname))
+
+        # The standard validation layer has no library path.
+        if 'library_path' in data[data_key]:
+            prev_name = os.path.basename(data[data_key]['library_path'])
+            data[data_key]['library_path'] = prev_name
+
+        target_fname = os.path.join(target_dir, os.path.basename(json_fname))
+        with open(target_fname, 'wb') as outfile:
+            json.dump(data, outfile)
+
+    # Get the Vulkan version from the vulkan_core.h file
+    vk_header_filename = args.version_header
+    vk_version = None
+    with open(vk_header_filename) as vk_header_file:
+        for line in vk_header_file:
+            if line.startswith('#define VK_HEADER_VERSION'):
+                vk_version = line.split()[-1]
+                break
+    if not vk_version:
+        print('failed to extract vk_version', file=sys.stderr)
+        return 1
+
+    # Set json file prefix and suffix for generating files, default to Linux.
+    relative_path_prefix = '../lib'
+    file_type_suffix = '.so'
+    if platform.system() == 'Windows':
+        relative_path_prefix = r'..\\'  # json-escaped, hence two backslashes.
+        file_type_suffix = '.dll'
+
+    # For each *.json.in template files in source dir generate actual json file
+    # in target dir
+    if (set(glob_slash(os.path.join(source_dir, '*.json.in'))) !=
+            set(json_in_files)):
+        print('.json.in list in gn file is out-of-date', file=sys.stderr)
+        return 1
+    for json_in_name in json_in_files:
+        if not json_in_name.endswith('.json.in'):
+            continue
+        json_in_fname = os.path.basename(json_in_name)
+        layer_name = json_in_fname[:-len('.json.in')]
+        layer_lib_name = layer_name + file_type_suffix
+        json_out_fname = os.path.join(target_dir, json_in_fname[:-len('.in')])
+        with open(json_out_fname,'w') as json_out_file, \
+             open(json_in_name) as infile:
+            for line in infile:
+                line = line.replace('@RELATIVE_LAYER_BINARY@',
+                                    relative_path_prefix + layer_lib_name)
+                line = line.replace('@VK_VERSION@', '1.1.' + vk_version)
+                json_out_file.write(line)
+
+if __name__ == '__main__':
+    sys.exit(main())
diff --git a/build-gn/secondary/build_overrides/build.gni b/build-gn/secondary/build_overrides/build.gni
new file mode 100644
index 0000000..c6c11fa
--- /dev/null
+++ b/build-gn/secondary/build_overrides/build.gni
@@ -0,0 +1,18 @@
+# Copyright (c) 2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+build_with_chromium = false
+ignore_elf32_limitations = true
+linux_use_bundled_binutils_override = false
+use_system_xcode = true
diff --git a/build-gn/secondary/build_overrides/vulkan_tools.gni b/build-gn/secondary/build_overrides/vulkan_tools.gni
new file mode 100644
index 0000000..9f80846
--- /dev/null
+++ b/build-gn/secondary/build_overrides/vulkan_tools.gni
@@ -0,0 +1,21 @@
+# Copyright (c) 2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Paths to vulkan tools dependencies
+vulkan_headers_dir = "//external/Vulkan-Headers"
+
+# Subdirectories for generated files
+vulkan_data_subdir = ""
+vulkan_gen_subdir = ""
+
diff --git a/build-gn/update_deps.sh b/build-gn/update_deps.sh
new file mode 100755
index 0000000..41da2ab
--- /dev/null
+++ b/build-gn/update_deps.sh
@@ -0,0 +1,37 @@
+#!/bin/sh
+
+# Copyright (c) 2019 LunarG, Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Execute at repo root
+cd "$(dirname $0)/.."
+
+# Use update_deps.py to update source dependencies from /scripts/known_good.json
+scripts/update_deps.py --dir="external" --no-build
+
+# Use gclient to update toolchain dependencies from /build-gn/DEPS (from chromium)
+cat << EOF >> .gclient
+solutions = [
+  { "name"        : ".",
+    "url"         : "https://github.com/KhronosGroup/Vulkan-Tools",
+    "deps_file"   : "build-gn/DEPS",
+    "managed"     : False,
+    "custom_deps" : {
+    },
+    "custom_vars": {},
+  },
+]
+EOF
+gclient sync
+
diff --git a/cube/cube.c b/cube/cube.c
index b702b28..ff4d5a6 100644
--- a/cube/cube.c
+++ b/cube/cube.c
@@ -1084,6 +1084,9 @@
         .pImageIndices = &demo->current_buffer,
     };
 
+    VkRectLayerKHR rect;
+    VkPresentRegionKHR region;
+    VkPresentRegionsKHR regions;
     if (demo->VK_KHR_incremental_present_enabled) {
         // If using VK_KHR_incremental_present, we provide a hint of the region
         // that contains changed content relative to the previously-presented
@@ -1093,23 +1096,20 @@
         // ensure that the entire image has the correctly-drawn content.
         uint32_t eighthOfWidth = demo->width / 8;
         uint32_t eighthOfHeight = demo->height / 8;
-        VkRectLayerKHR rect = {
-            .offset.x = eighthOfWidth,
-            .offset.y = eighthOfHeight,
-            .extent.width = eighthOfWidth * 6,
-            .extent.height = eighthOfHeight * 6,
-            .layer = 0,
-        };
-        VkPresentRegionKHR region = {
-            .rectangleCount = 1,
-            .pRectangles = &rect,
-        };
-        VkPresentRegionsKHR regions = {
-            .sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR,
-            .pNext = present.pNext,
-            .swapchainCount = present.swapchainCount,
-            .pRegions = &region,
-        };
+
+        rect.offset.x = eighthOfWidth;
+        rect.offset.y = eighthOfHeight;
+        rect.extent.width = eighthOfWidth * 6;
+        rect.extent.height = eighthOfHeight * 6;
+        rect.layer = 0;
+
+        region.rectangleCount = 1;
+        region.pRectangles = &rect;
+
+        regions.sType = VK_STRUCTURE_TYPE_PRESENT_REGIONS_KHR;
+        regions.pNext = present.pNext;
+        regions.swapchainCount = present.swapchainCount;
+        regions.pRegions = &region;
         present.pNext = &regions;
     }
 
@@ -1381,6 +1381,10 @@
         demo->next_present_id = 1;
     }
 
+    if (NULL != swapchainImages) {
+        free(swapchainImages);
+    }
+
     if (NULL != presentModes) {
         free(presentModes);
     }
@@ -2918,47 +2922,28 @@
     VkResult err;
     uint32_t instance_extension_count = 0;
     uint32_t instance_layer_count = 0;
-    uint32_t validation_layer_count = 0;
-    char **instance_validation_layers = NULL;
+    char *instance_validation_layers[] = {"VK_LAYER_KHRONOS_validation"};
     demo->enabled_extension_count = 0;
     demo->enabled_layer_count = 0;
     demo->is_minimized = false;
     demo->cmd_pool = VK_NULL_HANDLE;
 
-    char *instance_validation_layers_alt1[] = {"VK_LAYER_LUNARG_standard_validation"};
-
-    char *instance_validation_layers_alt2[] = {"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
-                                               "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
-                                               "VK_LAYER_GOOGLE_unique_objects"};
-
-    /* Look for validation layers */
+    // Look for validation layers
     VkBool32 validation_found = 0;
     if (demo->validate) {
         err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL);
         assert(!err);
 
-        instance_validation_layers = instance_validation_layers_alt1;
         if (instance_layer_count > 0) {
             VkLayerProperties *instance_layers = malloc(sizeof(VkLayerProperties) * instance_layer_count);
             err = vkEnumerateInstanceLayerProperties(&instance_layer_count, instance_layers);
             assert(!err);
 
-            validation_found = demo_check_layers(ARRAY_SIZE(instance_validation_layers_alt1), instance_validation_layers,
+            validation_found = demo_check_layers(ARRAY_SIZE(instance_validation_layers), instance_validation_layers,
                                                  instance_layer_count, instance_layers);
             if (validation_found) {
-                demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
-                demo->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
-                validation_layer_count = 1;
-            } else {
-                // use alternative set of validation layers
-                instance_validation_layers = instance_validation_layers_alt2;
-                demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
-                validation_found = demo_check_layers(ARRAY_SIZE(instance_validation_layers_alt2), instance_validation_layers,
-                                                     instance_layer_count, instance_layers);
-                validation_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
-                for (uint32_t i = 0; i < validation_layer_count; i++) {
-                    demo->enabled_layers[i] = instance_validation_layers[i];
-                }
+                demo->enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
+                demo->enabled_layers[0] = "VK_LAYER_KHRONOS_validation";
             }
             free(instance_layers);
         }
@@ -3492,6 +3477,7 @@
         demo->format = surfFormats[0].format;
     }
     demo->color_space = surfFormats[0].colorSpace;
+    free(surfFormats);
 
     demo->quit = false;
     demo->curFrame = 0;
diff --git a/cube/cube.cpp b/cube/cube.cpp
index a6ac4ff..965f6fa 100644
--- a/cube/cube.cpp
+++ b/cube/cube.cpp
@@ -34,6 +34,7 @@
 
 #define VULKAN_HPP_NO_SMART_HANDLE
 #define VULKAN_HPP_NO_EXCEPTIONS
+#define VULKAN_HPP_TYPESAFE_CONVERSION
 #include <vulkan/vulkan.hpp>
 #include <vulkan/vk_sdk_platform.h>
 
@@ -537,6 +538,7 @@
       width{0},
       height{0},
       swapchainImageCount{0},
+      presentMode{vk::PresentModeKHR::eFifo},
       frame_index{0},
       spin_angle{0.0f},
       spin_increment{0.0f},
@@ -1008,45 +1010,26 @@
 void Demo::init_vk() {
     uint32_t instance_extension_count = 0;
     uint32_t instance_layer_count = 0;
-    uint32_t validation_layer_count = 0;
-    char const *const *instance_validation_layers = nullptr;
+    char const *const instance_validation_layers[] = {"VK_LAYER_KHRONOS_validation"};
     enabled_extension_count = 0;
     enabled_layer_count = 0;
 
-    char const *const instance_validation_layers_alt1[] = {"VK_LAYER_LUNARG_standard_validation"};
-
-    char const *const instance_validation_layers_alt2[] = {"VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation",
-                                                           "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation",
-                                                           "VK_LAYER_GOOGLE_unique_objects"};
-
     // Look for validation layers
     vk::Bool32 validation_found = VK_FALSE;
     if (validate) {
         auto result = vk::enumerateInstanceLayerProperties(&instance_layer_count, static_cast<vk::LayerProperties *>(nullptr));
         VERIFY(result == vk::Result::eSuccess);
 
-        instance_validation_layers = instance_validation_layers_alt1;
         if (instance_layer_count > 0) {
             std::unique_ptr<vk::LayerProperties[]> instance_layers(new vk::LayerProperties[instance_layer_count]);
             result = vk::enumerateInstanceLayerProperties(&instance_layer_count, instance_layers.get());
             VERIFY(result == vk::Result::eSuccess);
 
-            validation_found = check_layers(ARRAY_SIZE(instance_validation_layers_alt1), instance_validation_layers,
+            validation_found = check_layers(ARRAY_SIZE(instance_validation_layers), instance_validation_layers,
                                             instance_layer_count, instance_layers.get());
             if (validation_found) {
-                enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt1);
-                enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation";
-                validation_layer_count = 1;
-            } else {
-                // use alternative set of validation layers
-                instance_validation_layers = instance_validation_layers_alt2;
-                enabled_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
-                validation_found = check_layers(ARRAY_SIZE(instance_validation_layers_alt2), instance_validation_layers,
-                                                instance_layer_count, instance_layers.get());
-                validation_layer_count = ARRAY_SIZE(instance_validation_layers_alt2);
-                for (uint32_t i = 0; i < validation_layer_count; i++) {
-                    enabled_layers[i] = instance_validation_layers[i];
-                }
+                enabled_layer_count = ARRAY_SIZE(instance_validation_layers);
+                enabled_layers[0] = "VK_LAYER_KHRONOS_validation";
             }
         }
 
diff --git a/scripts/common_codegen.py b/scripts/common_codegen.py
index 47bb632..8954532 100644
--- a/scripts/common_codegen.py
+++ b/scripts/common_codegen.py
@@ -50,6 +50,7 @@
 platform_dict = {
     'android' : 'VK_USE_PLATFORM_ANDROID_KHR',
     'fuchsia' : 'VK_USE_PLATFORM_FUCHSIA',
+    'ggp': 'VK_USE_PLATFORM_GGP',
     'ios' : 'VK_USE_PLATFORM_IOS_MVK',
     'macos' : 'VK_USE_PLATFORM_MACOS_MVK',
     'metal' : 'VK_USE_PLATFORM_METAL_EXT',
diff --git a/scripts/known_good.json b/scripts/known_good.json
index 0bb2287..705c06e 100644
--- a/scripts/known_good.json
+++ b/scripts/known_good.json
@@ -6,7 +6,7 @@
       "sub_dir" : "glslang",
       "build_dir" : "glslang/build",
       "install_dir" : "glslang/build/install",
-      "commit" : "5432f0dd8f331f15182681664d7486681e8514e6",
+      "commit" : "e06c7e9a515b716c731bda13f507546f107775d1",
       "prebuild" : [
         "python update_glslang_sources.py"
       ]
@@ -17,7 +17,7 @@
       "sub_dir" : "Vulkan-Headers",
       "build_dir" : "Vulkan-Headers/build",
       "install_dir" : "Vulkan-Headers/build/install",
-      "commit" : "v1.1.102"
+      "commit" : "v1.1.108"
     },
     {
       "name" : "MoltenVK",
@@ -25,7 +25,7 @@
       "sub_dir" : "MoltenVK",
       "build_dir" : "MoltenVK",
       "install_dir" : "MoltenVK",
-      "commit" : "f969bcc937674989ee5ea8e3cf8e35184134f29d",
+      "commit" : "v1.0.34",
       "custom_build" : [
         "./fetchDependencies --v-headers-root {0[Vulkan-Headers][repo_dir]} --glslang-root {0[glslang][repo_dir]}",
         "xcodebuild -project MoltenVKPackaging.xcodeproj GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS MVK_LOGGING_ENABLED=0' -scheme \"MoltenVK Package\" build"
@@ -41,7 +41,7 @@
       "sub_dir" : "Vulkan-Loader",
       "build_dir" : "Vulkan-Loader/build",
       "install_dir" : "Vulkan-Loader/build/install",
-      "commit" : "v1.1.102",
+      "commit" : "v1.1.108",
       "deps" : [
         {
           "var_name" : "VULKAN_HEADERS_INSTALL_DIR",
diff --git a/scripts/kvt_genvk.py b/scripts/kvt_genvk.py
index 399c35b..598f000 100644
--- a/scripts/kvt_genvk.py
+++ b/scripts/kvt_genvk.py
@@ -112,10 +112,14 @@
     # Defaults for generating re-inclusion protection wrappers (or not)
     protectFeature = protect
 
+    # An API style convention object
+    conventions = VulkanConventions()
+
     # Helper file generator options for typemap_helper.h
     genOpts['vk_typemap_helper.h'] = [
           HelperFileOutputGenerator,
           HelperFileOutputGeneratorOptions(
+            conventions       = conventions,
             filename          = 'vk_typemap_helper.h',
             directory         = directory,
             apiname           = 'vulkan',
@@ -140,6 +144,7 @@
     genOpts['mock_icd.h'] = [
           MockICDOutputGenerator,
           MockICDGeneratorOptions(
+            conventions       = conventions,
             filename          = 'mock_icd.h',
             directory         = directory,
             apiname           = 'vulkan',
@@ -164,6 +169,7 @@
     genOpts['mock_icd.cpp'] = [
           MockICDOutputGenerator,
           MockICDGeneratorOptions(
+            conventions       = conventions,
             filename          = 'mock_icd.cpp',
             directory         = directory,
             apiname           = 'vulkan',
@@ -296,6 +302,9 @@
     # Generator Modifications
     from mock_icd_generator import MockICDGeneratorOptions, MockICDOutputGenerator
     from vulkan_tools_helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions
+    # Temporary workaround for vkconventions python2 compatibility
+    import abc; abc.ABC = abc.ABCMeta('ABC', (object,), {})
+    from vkconventions import VulkanConventions
 
     # This splits arguments which are space-separated lists
     args.feature = [name for arg in args.feature for name in arg.split()]
diff --git a/scripts/mock_icd_generator.py b/scripts/mock_icd_generator.py
index 4cbd831..48d9465 100644
--- a/scripts/mock_icd_generator.py
+++ b/scripts/mock_icd_generator.py
@@ -934,6 +934,7 @@
 #     separate line, align parameter names at the specified column
 class MockICDGeneratorOptions(GeneratorOptions):
     def __init__(self,
+                 conventions = None,
                  filename = None,
                  directory = '.',
                  apiname = None,
@@ -959,7 +960,7 @@
                  alignFuncParam = 0,
                  expandEnumerants = True,
                  helper_file_type = ''):
-        GeneratorOptions.__init__(self, filename, directory, apiname, profile,
+        GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
                                   versions, emitversions, defaultExtensions,
                                   addExtensions, removeExtensions, emitExtensions, sortProcedure)
         self.prefixText      = prefixText
diff --git a/scripts/update_deps.py b/scripts/update_deps.py
index 5d00eb5..f1fe36d 100755
--- a/scripts/update_deps.py
+++ b/scripts/update_deps.py
@@ -343,7 +343,7 @@
     def Checkout(self):
         print('Checking out {n} in {d}'.format(n=self.name, d=self.repo_dir))
         if self._args.do_clean_repo:
-            shutil.rmtree(self.repo_dir)
+            shutil.rmtree(self.repo_dir, ignore_errors=True)
         if not os.path.exists(os.path.join(self.repo_dir, '.git')):
             self.Clone()
         self.Fetch()
@@ -415,6 +415,12 @@
                 cmake_cmd.append('-A')
                 cmake_cmd.append('x64')
 
+        # Apply a generator, if one is specified.  This can be used to supply
+        # a specific generator for the dependent repositories to match
+        # that of the main repository.
+        if self._args.generator is not None:
+            cmake_cmd.extend(['-G', self._args.generator])
+
         if VERBOSE:
             print("CMake command: " + " ".join(cmake_cmd))
 
@@ -435,8 +441,15 @@
         # Speed up the build.
         if platform.system() == 'Linux' or platform.system() == 'Darwin':
             cmake_cmd.append('--')
-            cmake_cmd.append('-j{ncpu}'
-                             .format(ncpu=multiprocessing.cpu_count()))
+            num_make_jobs = multiprocessing.cpu_count()
+            env_make_jobs = os.environ.get('MAKE_JOBS', None)
+            if env_make_jobs is not None:
+                try:
+                    num_make_jobs = min(num_make_jobs, int(env_make_jobs))
+                except ValueError:
+                    print('warning: environment variable MAKE_JOBS has non-numeric value "{}".  '
+                          'Using {} (CPU count) instead.'.format(env_make_jobs, num_make_jobs))
+            cmake_cmd.append('-j{}'.format(num_make_jobs))
         if platform.system() == 'Windows':
             cmake_cmd.append('--')
             cmake_cmd.append('/maxcpucount')
@@ -594,6 +607,11 @@
         type=str.lower,
         help="Set build files configuration",
         default='debug')
+    parser.add_argument(
+        '--generator',
+        dest='generator',
+        help="Set the CMake generator",
+        default=None)
 
     args = parser.parse_args()
     save_cwd = os.getcwd()
@@ -628,7 +646,7 @@
                       'build_platforms',
                       'repo_dir',
                       'on_build_platform')
-        repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list};
+        repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list}
 
         # If the repo has a CI whitelist, skip the repo unless
         # one of the CI's environment variable is set to true.
diff --git a/scripts/vulkan_tools_helper_file_generator.py b/scripts/vulkan_tools_helper_file_generator.py
index e6e690f..ca5b240 100644
--- a/scripts/vulkan_tools_helper_file_generator.py
+++ b/scripts/vulkan_tools_helper_file_generator.py
@@ -31,6 +31,7 @@
 # HelperFileOutputGeneratorOptions - subclass of GeneratorOptions.
 class HelperFileOutputGeneratorOptions(GeneratorOptions):
     def __init__(self,
+                 conventions = None,
                  filename = None,
                  directory = '.',
                  apiname = None,
@@ -53,7 +54,7 @@
                  library_name = '',
                  expandEnumerants = True,
                  helper_file_type = ''):
-        GeneratorOptions.__init__(self, filename, directory, apiname, profile,
+        GeneratorOptions.__init__(self, conventions, filename, directory, apiname, profile,
                                   versions, emitversions, defaultExtensions,
                                   addExtensions, removeExtensions, emitExtensions, sortProcedure)
         self.prefixText       = prefixText
diff --git a/vulkaninfo/CMakeLists.txt b/vulkaninfo/CMakeLists.txt
index b9d0dfa..5a822c4 100644
--- a/vulkaninfo/CMakeLists.txt
+++ b/vulkaninfo/CMakeLists.txt
@@ -71,6 +71,13 @@
 
 if(WIN32)
     target_compile_definitions(vulkaninfo PUBLIC -DVK_USE_PLATFORM_WIN32_KHR -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS)
+    if(NOT MSVC_VERSION LESS 1900)
+        # Enable control flow guard
+        message(STATUS "Building vulkaninfo with control flow guard")
+        add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/guard:cf>")
+        set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf")
+        set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf")
+    endif()
 
     # Use static MSVCRT libraries
     foreach(configuration
diff --git a/vulkaninfo/json_validation_process.md b/vulkaninfo/json_validation_process.md
new file mode 100644
index 0000000..9434528
--- /dev/null
+++ b/vulkaninfo/json_validation_process.md
@@ -0,0 +1,38 @@
+# Validating [vulkaninfo](https://github.com/KhronosGroup/Vulkan-Tools/tree/master/vulkaninfo) JSON output
+
+The format of vulkaninfo's JSON output is designed to be used as input to the LunarG
+[Device Simulation](https://github.com/LunarG/VulkanTools/blob/master/layersvt/device_simulation.md)
+(DevSim) layer.
+When changes are made to vulkaninfo's JSON output, the formatting should be
+validated against DevSim's JSON schema, to ensure the text is correctly
+formatted.
+
+The DevSim JSON schema specifies exactly how its JSON input data must
+be structured.
+The schema may be found at
+https://schema.khronos.org/vulkan/devsim_1_0_0.json
+
+## Steps to validate JSON data against the DevSim schema
+
+1. Generate the text to be tested using `vulkaninfo --json` and save to a file.
+1. Download the [DevSim schema](https://schema.khronos.org/vulkan/devsim_1_0_0.json) to another file.
+1. For each of the on-line JSON validator tools listed below:
+   1. Paste the schema and and sample text into the `schema` and `data` fields.
+   1. Depending on the tool, it may validate automatically, or require clicking a `validate` button.
+   1. Ensure the tool reports no errors.
+
+## List of recommended JSON validator tools
+
+Each of these tools seem to have their own quirks and/or holes in coverage.
+I recommend using all of them, ensuring they all report that the data successfully
+validates against the schema.
+* https://www.jsonschemavalidator.net/
+* https://jsonschemalint.com/#/version/draft-04/markup/json
+* https://json-schema-validator.herokuapp.com/index.jsp
+
+If you have suggestions for better tools
+(e.g.: an official reference validator,
+an automatable tool to integrate with continuous integration)
+please create an
+[issue](https://github.com/KhronosGroup/Vulkan-Tools/issues)
+to recommend it.
diff --git a/vulkaninfo/vulkaninfo.c b/vulkaninfo/vulkaninfo.c
index b6463b2..8570ed8 100644
--- a/vulkaninfo/vulkaninfo.c
+++ b/vulkaninfo/vulkaninfo.c
@@ -112,11 +112,17 @@
     VkExtensionProperties *extension_properties;
 };
 
-struct SurfaceNameWHandle {
+struct AppInstance;
+
+struct SurfaceExtensionNode {
+    struct SurfaceExtensionNode *next;
+
     const char *name;
+    void (*create_window)(struct AppInstance *);
+    VkSurfaceKHR (*create_surface)(struct AppInstance *);
+    void (*destroy_window)(struct AppInstance *);
     VkSurfaceKHR surface;
-    struct SurfaceNameWHandle *pNextSurface;
-    VkBool32 present_support;
+    VkBool32 supports_present;
 };
 
 struct AppInstance {
@@ -148,13 +154,8 @@
     PFN_vkGetPhysicalDeviceSurfaceCapabilities2KHR vkGetPhysicalDeviceSurfaceCapabilities2KHR;
     PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT vkGetPhysicalDeviceSurfaceCapabilities2EXT;
 
-    VkSurfaceCapabilitiesKHR surface_capabilities;
-    VkSurfaceCapabilities2KHR surface_capabilities2;
-    VkSharedPresentSurfaceCapabilitiesKHR shared_surface_capabilities;
-    VkSurfaceCapabilities2EXT surface_capabilities2_ext;
+    struct SurfaceExtensionNode *surface_ext_infos_root;
 
-    struct SurfaceNameWHandle *surface_chain;
-    VkSurfaceKHR surface;
     int width, height;
 
 #ifdef VK_USE_PLATFORM_WIN32_KHR
@@ -182,6 +183,15 @@
 #endif
 };
 
+struct MemResSupport {
+    struct MemImageSupport {
+        bool regular_supported, sparse_supported, transient_supported;
+        VkFormat format;
+        uint32_t regular_memtypes, sparse_memtypes, transient_memtypes;
+    } image[2][1 + 7];
+    // TODO: buffers
+};
+
 struct AppGpu {
     uint32_t id;
     VkPhysicalDevice obj;
@@ -199,12 +209,17 @@
     VkPhysicalDeviceMemoryProperties memory_props;
     VkPhysicalDeviceMemoryProperties2KHR memory_props2;
 
+    struct MemResSupport mem_type_res_support;
+
     VkPhysicalDeviceFeatures features;
     VkPhysicalDeviceFeatures2KHR features2;
     VkPhysicalDevice limits;
 
     uint32_t device_extension_count;
     VkExtensionProperties *device_extensions;
+
+    VkDevice dev;
+    VkPhysicalDeviceFeatures enabled_features;
 };
 
 // return most severe flag only
@@ -293,6 +308,20 @@
     }
 }
 
+static const char *VkTilingString(const VkImageTiling tiling) {
+    switch (tiling) {
+#define STR(r)                \
+    case VK_IMAGE_TILING_##r: \
+        return #r
+        STR(OPTIMAL);
+        STR(LINEAR);
+        STR(DRM_FORMAT_MODIFIER_EXT);
+#undef STR
+        default:
+            return "UNKNOWN_TILING";
+    }
+}
+
 static const char *VkFormatString(VkFormat fmt) {
     switch (fmt) {
 #define STR(r)          \
@@ -552,7 +581,7 @@
 
 static bool CheckExtensionEnabled(const char *extension_to_check, const char **extension_list, uint32_t extension_count) {
     for (uint32_t i = 0; i < extension_count; ++i) {
-        if (!strcmp(extension_to_check, extension_list[i])) {
+        if (!strncmp(extension_to_check, extension_list[i], VK_MAX_EXTENSION_NAME_SIZE)) {
             return true;
         }
     }
@@ -562,7 +591,7 @@
 static bool CheckPhysicalDeviceExtensionIncluded(const char *extension_to_check, VkExtensionProperties *extension_list,
                                                  uint32_t extension_count) {
     for (uint32_t i = 0; i < extension_count; ++i) {
-        if (!strcmp(extension_to_check, extension_list[i].extensionName)) {
+        if (!strncmp(extension_to_check, extension_list[i].extensionName, VK_MAX_EXTENSION_NAME_SIZE)) {
             return true;
         }
     }
@@ -703,10 +732,10 @@
 // Prints opening code for html output file
 void PrintHtmlHeader(FILE *out) {
     fprintf(out, "<!doctype html>\n");
-    fprintf(out, "<html>\n");
+    fprintf(out, "<html lang='en'>\n");
     fprintf(out, "\t<head>\n");
     fprintf(out, "\t\t<title>vulkaninfo</title>\n");
-    fprintf(out, "\t\t<style type='text/css'>\n");
+    fprintf(out, "\t\t<style>\n");
     fprintf(out, "\t\thtml {\n");
     fprintf(out, "\t\t\tbackground-color: #0b1e48;\n");
     fprintf(out, "\t\t\tbackground-image: url(\"https://vulkan.lunarg.com/img/bg-starfield.jpg\");\n");
@@ -868,8 +897,6 @@
     inst->vulkan_minor = VK_VERSION_MINOR(inst->instance_version);
     inst->vulkan_patch = VK_VERSION_PATCH(VK_HEADER_VERSION);
 
-    inst->surface_chain = NULL;
-
     AppGetInstanceExtensions(inst);
 
     const VkDebugReportCallbackCreateInfoEXT dbg_info = {.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
@@ -897,6 +924,8 @@
     }
 
     AppLoadInstanceCommands(inst);
+
+    inst->surface_ext_infos_root = NULL;
 }
 
 static void AppDestroyInstance(struct AppInstance *inst) {
@@ -945,7 +974,9 @@
             {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT,
              .mem_size = sizeof(VkPhysicalDeviceTransformFeedbackPropertiesEXT)},
             {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_PROPERTIES_EXT,
-             .mem_size = sizeof(VkPhysicalDeviceFragmentDensityMapPropertiesEXT)}};
+             .mem_size = sizeof(VkPhysicalDeviceFragmentDensityMapPropertiesEXT)},
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR,
+             .mem_size = sizeof(VkPhysicalDeviceDepthStencilResolvePropertiesKHR)}};
 
         uint32_t chain_info_len = ARRAY_SIZE(chain_info);
 
@@ -1026,8 +1057,14 @@
 
     if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
                               gpu->inst->inst_extensions_count)) {
+        struct pNextChainBuildingBlockInfo mem_prop_chain_info[] = {
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT,
+             .mem_size = sizeof(VkPhysicalDeviceMemoryBudgetPropertiesEXT)}};
+
+        uint32_t mem_prop_chain_info_len = ARRAY_SIZE(mem_prop_chain_info);
+
         gpu->memory_props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PROPERTIES_2_KHR;
-        gpu->memory_props2.pNext = NULL;
+        buildpNextChain((struct VkStructureHeader *)&gpu->memory_props2, mem_prop_chain_info, mem_prop_chain_info_len);
 
         inst->vkGetPhysicalDeviceMemoryProperties2KHR(gpu->obj, &gpu->memory_props2);
 
@@ -1053,7 +1090,15 @@
             {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SCALAR_BLOCK_LAYOUT_FEATURES_EXT,
              .mem_size = sizeof(VkPhysicalDeviceScalarBlockLayoutFeaturesEXT)},
             {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FRAGMENT_DENSITY_MAP_FEATURES_EXT,
-             .mem_size = sizeof(VkPhysicalDeviceFragmentDensityMapFeaturesEXT)}};
+             .mem_size = sizeof(VkPhysicalDeviceFragmentDensityMapFeaturesEXT)},
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT,
+             .mem_size = sizeof(VkPhysicalDeviceMemoryPriorityFeaturesEXT)},
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT,
+             .mem_size = sizeof(VkPhysicalDeviceBufferAddressFeaturesEXT)},
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT,
+             .mem_size = sizeof(VkPhysicalDeviceYcbcrImageArraysFeaturesEXT)},
+            {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT,
+             .mem_size = sizeof(VkPhysicalDeviceHostQueryResetFeaturesEXT)}};
 
         uint32_t chain_info_len = ARRAY_SIZE(chain_info);
 
@@ -1064,9 +1109,127 @@
     }
 
     AppGetPhysicalDeviceLayerExtensions(gpu, NULL, &gpu->device_extension_count, &gpu->device_extensions);
+
+    const float queue_priority = 1.0f;
+    const VkDeviceQueueCreateInfo q_ci = {.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
+                                          .queueFamilyIndex = 0,  // just pick the first one and hope for the best
+                                          .queueCount = 1,
+                                          .pQueuePriorities = &queue_priority};
+    VkPhysicalDeviceFeatures features = {0};
+    // if (gpu->features.sparseBinding ) features.sparseBinding = VK_TRUE;
+    gpu->enabled_features = features;
+    const VkDeviceCreateInfo device_ci = {.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
+                                          .queueCreateInfoCount = 1,
+                                          .pQueueCreateInfos = &q_ci,
+                                          // TODO: relevant extensions
+                                          .pEnabledFeatures = &gpu->enabled_features};
+
+    VkResult err = vkCreateDevice(gpu->obj, &device_ci, NULL, &gpu->dev);
+    if (err) ERR_EXIT(err);
+
+    const VkFormat color_format = VK_FORMAT_R8G8B8A8_UNORM;
+    const VkFormat formats[] = {
+        color_format,      VK_FORMAT_D16_UNORM,         VK_FORMAT_X8_D24_UNORM_PACK32, VK_FORMAT_D32_SFLOAT,
+        VK_FORMAT_S8_UINT, VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT,   VK_FORMAT_D32_SFLOAT_S8_UINT};
+    assert(ARRAY_SIZE(gpu->mem_type_res_support.image[0]) == ARRAY_SIZE(formats));
+    const VkImageUsageFlags usages[] = {0, VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT};
+    const VkImageCreateFlags flagss[] = {0, VK_IMAGE_CREATE_SPARSE_BINDING_BIT};
+
+    for (size_t fmt_i = 0; fmt_i < ARRAY_SIZE(formats); ++fmt_i) {
+        for (VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; tiling <= VK_IMAGE_TILING_LINEAR; ++tiling) {
+            gpu->mem_type_res_support.image[tiling][fmt_i].format = formats[fmt_i];
+            gpu->mem_type_res_support.image[tiling][fmt_i].regular_supported = true;
+            gpu->mem_type_res_support.image[tiling][fmt_i].sparse_supported = true;
+            gpu->mem_type_res_support.image[tiling][fmt_i].transient_supported = true;
+
+            VkFormatProperties fmt_props;
+            vkGetPhysicalDeviceFormatProperties(gpu->obj, formats[fmt_i], &fmt_props);
+            if ((tiling == VK_IMAGE_TILING_OPTIMAL && fmt_props.optimalTilingFeatures == 0) ||
+                (tiling == VK_IMAGE_TILING_LINEAR && fmt_props.linearTilingFeatures == 0)) {
+                gpu->mem_type_res_support.image[tiling][fmt_i].regular_supported = false;
+                gpu->mem_type_res_support.image[tiling][fmt_i].sparse_supported = false;
+                gpu->mem_type_res_support.image[tiling][fmt_i].transient_supported = false;
+                continue;
+            }
+
+            for (size_t u_i = 0; u_i < ARRAY_SIZE(usages); ++u_i) {
+                for (size_t flg_i = 0; flg_i < ARRAY_SIZE(flagss); ++flg_i) {
+                    VkImageCreateInfo image_ci = {
+                        .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
+                        .flags = flagss[flg_i],
+                        .imageType = VK_IMAGE_TYPE_2D,
+                        .format = formats[fmt_i],
+                        .extent = {8, 8, 1},
+                        .mipLevels = 1,
+                        .arrayLayers = 1,
+                        .samples = VK_SAMPLE_COUNT_1_BIT,
+                        .tiling = tiling,
+                        .usage = usages[u_i],
+                    };
+
+                    if ((image_ci.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) &&
+                        (image_ci.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
+                        continue;
+                    }
+
+                    if (image_ci.usage == 0 || (image_ci.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
+                        if (image_ci.format == color_format)
+                            image_ci.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
+                        else
+                            image_ci.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
+                    }
+
+                    if (!gpu->enabled_features.sparseBinding && (image_ci.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT)) {
+                        gpu->mem_type_res_support.image[tiling][fmt_i].sparse_supported = false;
+                        continue;
+                    }
+
+                    VkImageFormatProperties img_props;
+                    err = vkGetPhysicalDeviceImageFormatProperties(gpu->obj, image_ci.format, image_ci.imageType, image_ci.tiling,
+                                                                   image_ci.usage, image_ci.flags, &img_props);
+
+                    uint32_t *memtypes;
+                    bool *support;
+
+                    if (image_ci.flags == 0 && !(image_ci.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
+                        memtypes = &gpu->mem_type_res_support.image[tiling][fmt_i].regular_memtypes;
+                        support = &gpu->mem_type_res_support.image[tiling][fmt_i].regular_supported;
+                    } else if ((image_ci.flags & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) &&
+                               !(image_ci.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
+                        memtypes = &gpu->mem_type_res_support.image[tiling][fmt_i].sparse_memtypes;
+                        support = &gpu->mem_type_res_support.image[tiling][fmt_i].sparse_supported;
+                    } else if (image_ci.flags == 0 && (image_ci.usage & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT)) {
+                        memtypes = &gpu->mem_type_res_support.image[tiling][fmt_i].transient_memtypes;
+                        support = &gpu->mem_type_res_support.image[tiling][fmt_i].transient_supported;
+                    } else {
+                        assert(false);
+                    }
+
+                    if (err == VK_ERROR_FORMAT_NOT_SUPPORTED) {
+                        *support = false;
+                    } else {
+                        if (err) ERR_EXIT(err);
+
+                        VkImage dummy_img;
+                        err = vkCreateImage(gpu->dev, &image_ci, NULL, &dummy_img);
+                        if (err) ERR_EXIT(err);
+
+                        VkMemoryRequirements mem_req;
+                        vkGetImageMemoryRequirements(gpu->dev, dummy_img, &mem_req);
+                        *memtypes = mem_req.memoryTypeBits;
+
+                        vkDestroyImage(gpu->dev, dummy_img, NULL);
+                    }
+                }
+            }
+        }
+    }
+    // TODO buffer - memory type compatibility
 }
 
 static void AppGpuDestroy(struct AppGpu *gpu) {
+    vkDestroyDevice(gpu->dev, NULL);
+
     free(gpu->device_extensions);
 
     if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
@@ -1143,15 +1306,18 @@
     }
 }
 
-static void AppCreateWin32Surface(struct AppInstance *inst) {
+static VkSurfaceKHR AppCreateWin32Surface(struct AppInstance *inst) {
     VkWin32SurfaceCreateInfoKHR createInfo;
     createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
     createInfo.pNext = NULL;
     createInfo.flags = 0;
     createInfo.hinstance = inst->h_instance;
     createInfo.hwnd = inst->h_wnd;
-    VkResult err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
+
+    VkSurfaceKHR surface;
+    VkResult err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &surface);
     if (err) ERR_EXIT(err);
+    return surface;
 }
 
 static void AppDestroyWin32Window(struct AppInstance *inst) { DestroyWindow(inst->h_wnd); }
@@ -1160,15 +1326,8 @@
 
 #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) || \
     defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_WAYLAND_KHR) || defined(VK_USE_PLATFORM_ANDROID_KHR)
-static void AppDestroySurface(struct AppInstance *inst) {  // same for all platforms
-    vkDestroySurfaceKHR(inst->instance, inst->surface, NULL);
-}
-
-static void AppDestroySurfaceChain(struct AppInstance *inst) {  // same for all platforms
-    for (struct SurfaceNameWHandle *surface_stuff = inst->surface_chain; surface_stuff != NULL;
-         surface_stuff = surface_stuff->pNextSurface) {
-        vkDestroySurfaceKHR(inst->instance, surface_stuff->surface, NULL);
-    }
+static void AppDestroySurface(struct AppInstance *inst, VkSurfaceKHR surface) {  // same for all platforms
+    vkDestroySurfaceKHR(inst->instance, surface, NULL);
 }
 #endif
 
@@ -1208,9 +1367,9 @@
     free(reply);
 }
 
-static void AppCreateXcbSurface(struct AppInstance *inst) {
+static VkSurfaceKHR AppCreateXcbSurface(struct AppInstance *inst) {
     if (!inst->xcb_connection) {
-        return;
+        ERR_EXIT(VK_ERROR_INITIALIZATION_FAILED);
     }
 
     VkXcbSurfaceCreateInfoKHR xcb_createInfo;
@@ -1219,8 +1378,11 @@
     xcb_createInfo.flags = 0;
     xcb_createInfo.connection = inst->xcb_connection;
     xcb_createInfo.window = inst->xcb_window;
-    VkResult err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface);
+
+    VkSurfaceKHR surface;
+    VkResult err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &surface);
     if (err) ERR_EXIT(err);
+    return surface;
 }
 
 static void AppDestroyXcbWindow(struct AppInstance *inst) {
@@ -1256,15 +1418,18 @@
     XFree(visualInfo);
 }
 
-static void AppCreateXlibSurface(struct AppInstance *inst) {
+static VkSurfaceKHR AppCreateXlibSurface(struct AppInstance *inst) {
     VkXlibSurfaceCreateInfoKHR createInfo;
     createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
     createInfo.pNext = NULL;
     createInfo.flags = 0;
     createInfo.dpy = inst->xlib_display;
     createInfo.window = inst->xlib_window;
-    VkResult err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
+
+    VkSurfaceKHR surface;
+    VkResult err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &surface);
     if (err) ERR_EXIT(err);
+    return surface;
 }
 
 static void AppDestroyXlibWindow(struct AppInstance *inst) {
@@ -1284,15 +1449,17 @@
     }
 }
 
-static void AppCreateMacOSSurface(struct AppInstance *inst) {
-    VkMacOSSurfaceCreateInfoMVK surface;
-    surface.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
-    surface.pNext = NULL;
-    surface.flags = 0;
-    surface.pView = inst->window;
+static VkSurfaceKHR AppCreateMacOSSurface(struct AppInstance *inst) {
+    VkMacOSSurfaceCreateInfoMVK createInfo;
+    createInfo.sType = VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK;
+    createInfo.pNext = NULL;
+    createInfo.flags = 0;
+    createInfo.pView = inst->window;
 
-    VkResult err = vkCreateMacOSSurfaceMVK(inst->instance, &surface, NULL, &inst->surface);
+    VkSurfaceKHR surface;
+    VkResult err = vkCreateMacOSSurfaceMVK(inst->instance, &createInfo, NULL, &surface);
     if (err) ERR_EXIT(err);
+    return surface;
 }
 
 static void AppDestroyMacOSWindow(struct AppInstance *inst) { DestroyMetalView(inst->window); }
@@ -1320,15 +1487,18 @@
     wl_registry_destroy(registry);
 }
 
-static void AppCreateWaylandSurface(struct AppInstance *inst) {
+static VkSurfaceKHR AppCreateWaylandSurface(struct AppInstance *inst) {
     VkWaylandSurfaceCreateInfoKHR createInfo;
     createInfo.sType = VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR;
     createInfo.pNext = NULL;
     createInfo.flags = 0;
     createInfo.display = inst->wayland_display;
     createInfo.surface = inst->wayland_surface;
-    VkResult err = vkCreateWaylandSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
+
+    VkSurfaceKHR surface;
+    VkResult err = vkCreateWaylandSurfaceKHR(inst->instance, &createInfo, NULL, &surface);
     if (err) ERR_EXIT(err);
+    return surface;
 }
 
 static void AppDestroyWaylandWindow(struct AppInstance *inst) { wl_display_disconnect(inst->wayland_display); }
@@ -1336,7 +1506,7 @@
 
 #if defined(VK_USE_PLATFORM_XCB_KHR) || defined(VK_USE_PLATFORM_XLIB_KHR) || defined(VK_USE_PLATFORM_WIN32_KHR) || \
     defined(VK_USE_PLATFORM_MACOS_MVK) || defined(VK_USE_PLATFORM_WAYLAND_KHR)
-static int AppDumpSurfaceFormats(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
+static int AppDumpSurfaceFormats(struct AppInstance *inst, struct AppGpu *gpu, VkSurfaceKHR surface, FILE *out) {
     // Get the list of VkFormat's that are supported
     VkResult err;
     uint32_t format_count = 0;
@@ -1344,7 +1514,7 @@
     VkSurfaceFormat2KHR *surf_formats2 = NULL;
 
     const VkPhysicalDeviceSurfaceInfo2KHR surface_info2 = {.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR,
-                                                           .surface = inst->surface};
+                                                           .surface = surface};
 
     if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
                               gpu->inst->inst_extensions_count)) {
@@ -1359,16 +1529,16 @@
         err = inst->vkGetPhysicalDeviceSurfaceFormats2KHR(gpu->obj, &surface_info2, &format_count, surf_formats2);
         if (err) ERR_EXIT(err);
     } else {
-        err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, NULL);
+        err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, surface, &format_count, NULL);
         if (err) ERR_EXIT(err);
         surf_formats = (VkSurfaceFormatKHR *)malloc(format_count * sizeof(VkSurfaceFormatKHR));
         if (!surf_formats) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
-        err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &format_count, surf_formats);
+        err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, surface, &format_count, surf_formats);
         if (err) ERR_EXIT(err);
     }
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t<details><summary>Formats: count = <div class='val'>%d</div></summary>", format_count);
+        fprintf(out, "\t\t\t\t\t<details><summary>Formats: count = <span class='val'>%d</span></summary>", format_count);
         if (format_count > 0) {
             fprintf(out, "\n");
         } else {
@@ -1381,10 +1551,10 @@
         if (html_output) {
             if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
                                       gpu->inst->inst_extensions_count)) {
-                fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>%s</div></summary></details>\n",
+                fprintf(out, "\t\t\t\t\t\t<details><summary><span class='type'>%s</span></summary></details>\n",
                         VkFormatString(surf_formats2[i].surfaceFormat.format));
             } else {
-                fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>%s</div></summary></details>\n",
+                fprintf(out, "\t\t\t\t\t\t<details><summary><span class='type'>%s</span></summary></details>\n",
                         VkFormatString(surf_formats[i].format));
             }
         } else if (human_readable_output) {
@@ -1412,20 +1582,21 @@
     return format_count;
 }
 
-static int AppDumpSurfacePresentModes(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
+static int AppDumpSurfacePresentModes(struct AppInstance *inst, struct AppGpu *gpu, VkSurfaceKHR surface, FILE *out) {
     // Get the list of VkPresentMode's that are supported:
     VkResult err;
     uint32_t present_mode_count = 0;
-    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, NULL);
+    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, surface, &present_mode_count, NULL);
     if (err) ERR_EXIT(err);
 
-    VkPresentModeKHR *surf_present_modes = (VkPresentModeKHR *)malloc(present_mode_count * sizeof(VkPresentInfoKHR));
+    VkPresentModeKHR *surf_present_modes = (VkPresentModeKHR *)malloc(present_mode_count * sizeof(VkPresentModeKHR));
     if (!surf_present_modes) ERR_EXIT(VK_ERROR_OUT_OF_HOST_MEMORY);
-    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, inst->surface, &present_mode_count, surf_present_modes);
+    err = inst->vkGetPhysicalDeviceSurfacePresentModesKHR(gpu->obj, surface, &present_mode_count, surf_present_modes);
     if (err) ERR_EXIT(err);
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t<details><summary>Present Modes: count = <div class='val'>%d</div></summary>", present_mode_count);
+        fprintf(out, "\t\t\t\t\t<details><summary>Present Modes: count = <span class='val'>%d</span></summary>",
+                present_mode_count);
         if (present_mode_count > 0) {
             fprintf(out, "\n");
         } else {
@@ -1436,7 +1607,7 @@
     }
     for (uint32_t i = 0; i < present_mode_count; ++i) {
         if (html_output) {
-            fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>%s</div></summary></details>\n",
+            fprintf(out, "\t\t\t\t\t\t<details><summary><span class='type'>%s</span></summary></details>\n",
                     VkPresentModeString(surf_present_modes[i]));
         } else if (human_readable_output) {
             printf("\t%s\n", VkPresentModeString(surf_present_modes[i]));
@@ -1453,308 +1624,311 @@
     return present_mode_count;
 }
 
-static void AppDumpSurfaceCapabilities(struct AppInstance *inst, struct AppGpu *gpu, FILE *out) {
+static void AppDumpSurfaceCapabilities(struct AppInstance *inst, struct AppGpu *gpu, VkSurfaceKHR surface, FILE *out) {
     if (CheckExtensionEnabled(VK_KHR_SURFACE_EXTENSION_NAME, gpu->inst->inst_extensions, gpu->inst->inst_extensions_count)) {
+        VkSurfaceCapabilitiesKHR surface_capabilities;
         VkResult err;
-        err = inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu->obj, inst->surface, &inst->surface_capabilities);
+        err = inst->vkGetPhysicalDeviceSurfaceCapabilitiesKHR(gpu->obj, surface, &surface_capabilities);
         if (err) ERR_EXIT(err);
 
         if (html_output) {
             fprintf(out, "\t\t\t\t\t<details><summary>VkSurfaceCapabilitiesKHR</summary>\n");
-            fprintf(out, "\t\t\t\t\t\t<details><summary>minImageCount = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.minImageCount);
-            fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageCount = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.maxImageCount);
+            fprintf(out, "\t\t\t\t\t\t<details><summary>minImageCount = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.minImageCount);
+            fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageCount = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.maxImageCount);
             fprintf(out, "\t\t\t\t\t\t<details><summary>currentExtent</summary>\n");
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.currentExtent.width);
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.currentExtent.height);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.currentExtent.width);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.currentExtent.height);
             fprintf(out, "\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t<details><summary>minImageExtent</summary>\n");
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.minImageExtent.width);
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.minImageExtent.height);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.minImageExtent.width);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.minImageExtent.height);
             fprintf(out, "\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageExtent</summary>\n");
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.maxImageExtent.width);
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.maxImageExtent.height);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>width = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.maxImageExtent.width);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>height = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.maxImageExtent.height);
             fprintf(out, "\t\t\t\t\t\t</details>\n");
-            fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageArrayLayers = <div class='val'>%u</div></summary></details>\n",
-                    inst->surface_capabilities.maxImageArrayLayers);
+            fprintf(out, "\t\t\t\t\t\t<details><summary>maxImageArrayLayers = <span class='val'>%u</span></summary></details>\n",
+                    surface_capabilities.maxImageArrayLayers);
             fprintf(out, "\t\t\t\t\t\t<details><summary>supportedTransform</summary>\n");
-            if (inst->surface_capabilities.supportedTransforms == 0) {
+            if (surface_capabilities.supportedTransforms == 0) {
                 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</span></summary></details>\n");
             }
             fprintf(out, "\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t<details><summary>currentTransform</summary>\n");
-            if (inst->surface_capabilities.currentTransform == 0) {
+            if (surface_capabilities.currentTransform == 0) {
                 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
             }
-            if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
+            if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
+                        "\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</div></summary></details>\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR</span></summary></details>\n");
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR</span></summary></details>\n");
             }
             fprintf(out, "\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t<details><summary>supportedCompositeAlpha</summary>\n");
-            if (inst->surface_capabilities.supportedCompositeAlpha == 0) {
+            if (surface_capabilities.supportedCompositeAlpha == 0) {
                 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR</span></summary></details>\n");
             }
             fprintf(out, "\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t<details><summary>supportedUsageFlags</summary>\n");
-            if (inst->surface_capabilities.supportedUsageFlags == 0) {
+            if (surface_capabilities.supportedUsageFlags == 0) {
                 fprintf(out, "\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
-                fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</div></summary></details>\n");
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
+                fprintf(
+                    out,
+                    "\t\t\t\t\t\t\t<details><summary><span class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
-                fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div class='type'>VK_IMAGE_USAGE_STORAGE_BIT</div></summary></details>\n");
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
+                fprintf(
+                    out,
+                    "\t\t\t\t\t\t\t<details><summary><span class='type'>VK_IMAGE_USAGE_STORAGE_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</span></summary></details>\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
                 fprintf(out,
-                        "\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</span></summary></details>\n");
             }
             fprintf(out, "\t\t\t\t\t\t</details>\n");
         } else if (human_readable_output) {
             printf("VkSurfaceCapabilitiesKHR:\n");
-            printf("\tminImageCount       = %u\n", inst->surface_capabilities.minImageCount);
-            printf("\tmaxImageCount       = %u\n", inst->surface_capabilities.maxImageCount);
+            printf("\tminImageCount       = %u\n", surface_capabilities.minImageCount);
+            printf("\tmaxImageCount       = %u\n", surface_capabilities.maxImageCount);
             printf("\tcurrentExtent:\n");
-            printf("\t\twidth       = %u\n", inst->surface_capabilities.currentExtent.width);
-            printf("\t\theight      = %u\n", inst->surface_capabilities.currentExtent.height);
+            printf("\t\twidth       = %u\n", surface_capabilities.currentExtent.width);
+            printf("\t\theight      = %u\n", surface_capabilities.currentExtent.height);
             printf("\tminImageExtent:\n");
-            printf("\t\twidth       = %u\n", inst->surface_capabilities.minImageExtent.width);
-            printf("\t\theight      = %u\n", inst->surface_capabilities.minImageExtent.height);
+            printf("\t\twidth       = %u\n", surface_capabilities.minImageExtent.width);
+            printf("\t\theight      = %u\n", surface_capabilities.minImageExtent.height);
             printf("\tmaxImageExtent:\n");
-            printf("\t\twidth       = %u\n", inst->surface_capabilities.maxImageExtent.width);
-            printf("\t\theight      = %u\n", inst->surface_capabilities.maxImageExtent.height);
-            printf("\tmaxImageArrayLayers = %u\n", inst->surface_capabilities.maxImageArrayLayers);
+            printf("\t\twidth       = %u\n", surface_capabilities.maxImageExtent.width);
+            printf("\t\theight      = %u\n", surface_capabilities.maxImageExtent.height);
+            printf("\tmaxImageArrayLayers = %u\n", surface_capabilities.maxImageArrayLayers);
             printf("\tsupportedTransform:\n");
-            if (inst->surface_capabilities.supportedTransforms == 0) {
+            if (surface_capabilities.supportedTransforms == 0) {
                 printf("\t\tNone\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
+            if (surface_capabilities.supportedTransforms & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n");
             }
             printf("\tcurrentTransform:\n");
-            if (inst->surface_capabilities.currentTransform == 0) {
+            if (surface_capabilities.currentTransform == 0) {
                 printf("\t\tNone\n");
             }
-            if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
+            if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR\n");
-            } else if (inst->surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
+            } else if (surface_capabilities.currentTransform & VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR) {
                 printf("\t\tVK_SURFACE_TRANSFORM_INHERIT_BIT_KHR\n");
             }
             printf("\tsupportedCompositeAlpha:\n");
-            if (inst->surface_capabilities.supportedCompositeAlpha == 0) {
+            if (surface_capabilities.supportedCompositeAlpha == 0) {
                 printf("\t\tNone\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR) {
                 printf("\t\tVK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR) {
                 printf("\t\tVK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR) {
                 printf("\t\tVK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR\n");
             }
-            if (inst->surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
+            if (surface_capabilities.supportedCompositeAlpha & VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR) {
                 printf("\t\tVK_COMPOSITE_ALPHA_INHERIT_BIT_KHR\n");
             }
             printf("\tsupportedUsageFlags:\n");
-            if (inst->surface_capabilities.supportedUsageFlags == 0) {
+            if (surface_capabilities.supportedUsageFlags == 0) {
                 printf("\t\tNone\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_TRANSFER_SRC_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_TRANSFER_DST_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_SAMPLED_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_STORAGE_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT\n");
             }
-            if (inst->surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
+            if (surface_capabilities.supportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
                 printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n");
             }
         }
@@ -1762,33 +1936,31 @@
         // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2EXT
         if (CheckExtensionEnabled(VK_EXT_DISPLAY_SURFACE_COUNTER_EXTENSION_NAME, gpu->inst->inst_extensions,
                                   gpu->inst->inst_extensions_count)) {
-            memset(&inst->surface_capabilities2_ext, 0, sizeof(VkSurfaceCapabilities2EXT));
-            inst->surface_capabilities2_ext.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT;
-            inst->surface_capabilities2_ext.pNext = NULL;
+            VkSurfaceCapabilities2EXT surface_capabilities2_ext = {VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_EXT};
 
-            err = inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT(gpu->obj, inst->surface, &inst->surface_capabilities2_ext);
+            err = inst->vkGetPhysicalDeviceSurfaceCapabilities2EXT(gpu->obj, surface, &surface_capabilities2_ext);
             if (err) ERR_EXIT(err);
 
             if (html_output) {
                 fprintf(out, "\t\t\t\t\t\t<details><summary>VkSurfaceCapabilities2EXT</summary>\n");
                 fprintf(out, "\t\t\t\t\t\t\t<details><summary>supportedSurfaceCounters</summary>\n");
-                if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) {
+                if (surface_capabilities2_ext.supportedSurfaceCounters == 0) {
                     fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
                 }
-                if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
+                if (surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
                     fprintf(out,
-                            "\t\t\t\t\t\t\t\t<details><summary><div "
-                            "class='type'>VK_SURFACE_COUNTER_VBLANK_EXT</div></summary></details>\n");
+                            "\t\t\t\t\t\t\t\t<details><summary><span "
+                            "class='type'>VK_SURFACE_COUNTER_VBLANK_EXT</span></summary></details>\n");
                 }
                 fprintf(out, "\t\t\t\t\t\t\t</details>\n");
                 fprintf(out, "\t\t\t\t\t\t</details>\n");
             } else if (human_readable_output) {
                 printf("VkSurfaceCapabilities2EXT:\n");
                 printf("\tsupportedSurfaceCounters:\n");
-                if (inst->surface_capabilities2_ext.supportedSurfaceCounters == 0) {
+                if (surface_capabilities2_ext.supportedSurfaceCounters == 0) {
                     printf("\t\tNone\n");
                 }
-                if (inst->surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
+                if (surface_capabilities2_ext.supportedSurfaceCounters & VK_SURFACE_COUNTER_VBLANK_EXT) {
                     printf("\t\tVK_SURFACE_COUNTER_VBLANK_EXT\n");
                 }
             }
@@ -1797,29 +1969,31 @@
         // Get additional surface capability information from vkGetPhysicalDeviceSurfaceCapabilities2KHR
         if (CheckExtensionEnabled(VK_KHR_GET_SURFACE_CAPABILITIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
                                   gpu->inst->inst_extensions_count)) {
-            if (CheckExtensionEnabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, gpu->inst->inst_extensions,
-                                      gpu->inst->inst_extensions_count)) {
-                inst->shared_surface_capabilities.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR;
-                inst->shared_surface_capabilities.pNext = NULL;
-                inst->surface_capabilities2.pNext = &inst->shared_surface_capabilities;
-            } else {
-                inst->surface_capabilities2.pNext = NULL;
-            }
+            VkSurfaceCapabilities2KHR surface_capabilities2;
 
-            inst->surface_capabilities2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
+            struct pNextChainBuildingBlockInfo sur_cap2_chain_info[] = {
+                {.sType = VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR,
+                 .mem_size = sizeof(VkSharedPresentSurfaceCapabilitiesKHR)}};
+
+            uint32_t sur_cap2_chain_info_len = ARRAY_SIZE(sur_cap2_chain_info);
+
+            surface_capabilities2.sType = VK_STRUCTURE_TYPE_SURFACE_CAPABILITIES_2_KHR;
+            buildpNextChain((struct VkStructureHeader *)&surface_capabilities2, sur_cap2_chain_info, sur_cap2_chain_info_len);
 
             VkPhysicalDeviceSurfaceInfo2KHR surface_info;
             surface_info.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SURFACE_INFO_2_KHR;
             surface_info.pNext = NULL;
-            surface_info.surface = inst->surface;
+            surface_info.surface = surface;
 
-            err = inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu->obj, &surface_info, &inst->surface_capabilities2);
+            err = inst->vkGetPhysicalDeviceSurfaceCapabilities2KHR(gpu->obj, &surface_info, &surface_capabilities2);
             if (err) ERR_EXIT(err);
 
-            void *place = inst->surface_capabilities2.pNext;
+            void *place = surface_capabilities2.pNext;
             while (place) {
                 struct VkStructureHeader *work = (struct VkStructureHeader *)place;
-                if (work->sType == VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR) {
+                if (work->sType == VK_STRUCTURE_TYPE_SHARED_PRESENT_SURFACE_CAPABILITIES_KHR &&
+                    CheckExtensionEnabled(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME, gpu->inst->inst_extensions,
+                                          gpu->inst->inst_extensions_count)) {
                     VkSharedPresentSurfaceCapabilitiesKHR *shared_surface_capabilities =
                         (VkSharedPresentSurfaceCapabilitiesKHR *)place;
                     if (html_output) {
@@ -1830,45 +2004,45 @@
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_TRANSFER_SRC_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_TRANSFER_DST_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_SAMPLED_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_SAMPLED_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_STORAGE_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_STORAGE_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_STORAGE_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags &
                             VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags &
                             VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</span></summary></details>\n");
                         }
                         if (shared_surface_capabilities->sharedPresentSupportedUsageFlags & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
                             fprintf(out,
-                                    "\t\t\t\t\t\t\t\t<details><summary><div "
-                                    "class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</div></summary></details>\n");
+                                    "\t\t\t\t\t\t\t\t<details><summary><span "
+                                    "class='type'>VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT</span></summary></details>\n");
                         }
                         fprintf(out, "\t\t\t\t\t\t\t</details>\n");
                         fprintf(out, "\t\t\t\t\t\t</details>\n");
@@ -1905,6 +2079,21 @@
                             printf("\t\tVK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT\n");
                         }
                     }
+                } else if (work->sType == VK_STRUCTURE_TYPE_SURFACE_PROTECTED_CAPABILITIES_KHR &&
+                           CheckExtensionEnabled(VK_KHR_SURFACE_PROTECTED_CAPABILITIES_EXTENSION_NAME, gpu->inst->inst_extensions,
+                                                 gpu->inst->inst_extensions_count)) {
+                    VkSurfaceProtectedCapabilitiesKHR *protected_surface_capabilities = (VkSurfaceProtectedCapabilitiesKHR *)place;
+                    if (html_output) {
+                        fprintf(out, "\t\t\t\t\t\t<details><summary>VkSurfaceProtectedCapabilities</summary>\n");
+                        fprintf(out,
+                                "\t\t\t\t\t\t\t<details><summary>supportsProtected = <span class='val'>%" PRIuLEAST32
+                                "</span></summary></details>\n",
+                                protected_surface_capabilities->supportsProtected);
+                        fprintf(out, "\t\t\t\t\t\t</details>\n");
+                    } else if (human_readable_output) {
+                        printf("VkSurfaceProtectedCapabilities\n");
+                        printf("\tsupportsProtected = %" PRIuLEAST32 "\n", protected_surface_capabilities->supportsProtected);
+                    }
                 }
                 place = work->pNext;
             }
@@ -1915,55 +2104,26 @@
     }
 }
 
-struct SurfaceExtensionInfo {
-    const char *name;
-    void (*create_window)(struct AppInstance *);
-    void (*create_surface)(struct AppInstance *);
-    void (*destroy_window)(struct AppInstance *);
-};
-
 static void AppDumpSurfaceExtension(struct AppInstance *inst, struct AppGpu *gpus, uint32_t gpu_count,
-                                    struct SurfaceExtensionInfo *surface_extension, int *format_count, int *present_mode_count,
+                                    struct SurfaceExtensionNode *surface_extension, int *format_count, int *present_mode_count,
                                     FILE *out) {
     if (!CheckExtensionEnabled(surface_extension->name, inst->inst_extensions, inst->inst_extensions_count)) {
         return;
     }
 
-    if (inst->surface) {
-        AppDestroySurface(inst);
-    }
-
-    surface_extension->create_window(inst);
-    surface_extension->create_surface(inst);
-
-    struct SurfaceNameWHandle *cur = inst->surface_chain;
-    if (cur == NULL) {
-        cur = (struct SurfaceNameWHandle *)malloc(sizeof(struct SurfaceNameWHandle));
-        inst->surface_chain = cur;
-    } else {
-        for (; cur->pNextSurface != NULL; cur = cur->pNextSurface) {
-        }
-        cur->pNextSurface = (struct SurfaceNameWHandle *)malloc(sizeof(struct SurfaceNameWHandle));
-        cur = cur->pNextSurface;
-    }
-    cur->name = surface_extension->name;
-    cur->surface = inst->surface;
-    cur->pNextSurface = NULL;
-    cur->present_support = VK_FALSE;
-
     for (uint32_t i = 0; i < gpu_count; ++i) {
         if (html_output) {
-            fprintf(out, "\t\t\t\t<details><summary>GPU id : <div class='val'>%u</div> (%s)</summary>\n", i,
+            fprintf(out, "\t\t\t\t<details><summary>GPU id : <span class='val'>%u</span> (%s)</summary>\n", i,
                     gpus[i].props.deviceName);
-            fprintf(out, "\t\t\t\t\t<details><summary>Surface type : <div class='type'>%s</div></summary></details>\n",
+            fprintf(out, "\t\t\t\t\t<details><summary>Surface type : <span class='type'>%s</span></summary></details>\n",
                     surface_extension->name);
         } else if (human_readable_output) {
             printf("GPU id       : %u (%s)\n", i, gpus[i].props.deviceName);
             printf("Surface type : %s\n", surface_extension->name);
         }
-        *format_count += AppDumpSurfaceFormats(inst, &gpus[i], out);
-        *present_mode_count += AppDumpSurfacePresentModes(inst, &gpus[i], out);
-        AppDumpSurfaceCapabilities(inst, &gpus[i], out);
+        *format_count += AppDumpSurfaceFormats(inst, &gpus[i], surface_extension->surface, out);
+        *present_mode_count += AppDumpSurfacePresentModes(inst, &gpus[i], surface_extension->surface, out);
+        AppDumpSurfaceCapabilities(inst, &gpus[i], surface_extension->surface, out);
 
         if (html_output) {
             fprintf(out, "\t\t\t\t</details>\n");
@@ -1971,8 +2131,6 @@
             printf("\n");
         }
     }
-    inst->surface = VK_NULL_HANDLE;
-    surface_extension->destroy_window(inst);
 }
 
 #endif
@@ -1993,7 +2151,7 @@
     features[2].flags = props.bufferFeatures;
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t\t<details><summary><div class='type'>FORMAT_%s</div></summary>\n", VkFormatString(fmt));
+        fprintf(out, "\t\t\t\t\t\t<details><summary><span class='type'>FORMAT_%s</span></summary>\n", VkFormatString(fmt));
     } else if (human_readable_output) {
         printf("\nFORMAT_%s:", VkFormatString(fmt));
     }
@@ -2003,71 +2161,72 @@
             if (features[i].flags == 0) {
                 fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>None</summary></details>\n");
             } else {
-                fprintf(out, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
-                        ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                     "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_"
-                                                                                     "BIT</div></summary></details>\n"
-                                                                                   : ""),  // 0x0001
-                        ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                     "class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_"
-                                                                                     "BIT</div></summary></details>\n"
-                                                                                   : ""),  // 0x0002
-                        ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</div></summary></details>\n"
-                             : ""),  // 0x0004
-                        ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT</div></summary></details>\n"
-                             : ""),  // 0x0008
-                        ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT</div></summary></details>\n"
-                             : ""),  // 0x0010
-                        ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT</div></summary></details>\n"
-                             : ""),  // 0x0020
-                        ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                     "class='type'>VK_FORMAT_FEATURE_VERTEX_BUFFER_"
-                                                                                     "BIT</div></summary></details>\n"
-                                                                                   : ""),  // 0x0040
-                        ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                        "class='type'>VK_FORMAT_FEATURE_COLOR_"
-                                                                                        "ATTACHMENT_BIT</div></summary></details>\n"
-                                                                                      : ""),  // 0x0080
-                        ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT</div></summary></details>\n"
-                             : ""),  // 0x0100
-                        ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</div></summary></details>\n"
-                             : ""),  // 0x0200
-                        ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                "class='type'>VK_FORMAT_FEATURE_BLIT_SRC_BIT</"
-                                                                                "div></summary></details>\n"
-                                                                              : ""),  // 0x0400
-                        ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                "class='type'>VK_FORMAT_FEATURE_BLIT_DST_BIT</"
-                                                                                "div></summary></details>\n"
-                                                                              : ""),  // 0x0800
-                        ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</div></summary></details>\n"
-                             : ""),  // 0x1000
-                        ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG)
-                             ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                               "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG</div></summary></details>\n"
-                             : ""),  // 0x2000
-                        ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                        "class='type'>VK_FORMAT_FEATURE_TRANSFER_"
-                                                                                        "SRC_BIT_KHR</div></summary></details>\n"
-                                                                                      : ""),  // 0x4000
-                        ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><div "
-                                                                                        "class='type'>VK_FORMAT_FEATURE_TRANSFER_"
-                                                                                        "DST_BIT_KHR</div></summary></details>\n"
-                                                                                      : ""));  // 0x8000
+                fprintf(
+                    out, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+                    ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                 "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_"
+                                                                                 "BIT</span></summary></details>\n"
+                                                                               : ""),  // 0x0001
+                    ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                 "class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_"
+                                                                                 "BIT</span></summary></details>\n"
+                                                                               : ""),  // 0x0002
+                    ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT</span></summary></details>\n"
+                         : ""),  // 0x0004
+                    ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT</span></summary></details>\n"
+                         : ""),  // 0x0008
+                    ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT</span></summary></details>\n"
+                         : ""),  // 0x0010
+                    ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT</span></summary></details>\n"
+                         : ""),  // 0x0020
+                    ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                 "class='type'>VK_FORMAT_FEATURE_VERTEX_BUFFER_"
+                                                                                 "BIT</span></summary></details>\n"
+                                                                               : ""),  // 0x0040
+                    ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                    "class='type'>VK_FORMAT_FEATURE_COLOR_"
+                                                                                    "ATTACHMENT_BIT</span></summary></details>\n"
+                                                                                  : ""),  // 0x0080
+                    ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT</span></summary></details>\n"
+                         : ""),  // 0x0100
+                    ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT</span></summary></details>\n"
+                         : ""),  // 0x0200
+                    ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                            "class='type'>VK_FORMAT_FEATURE_BLIT_SRC_BIT</"
+                                                                            "span></summary></details>\n"
+                                                                          : ""),  // 0x0400
+                    ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                            "class='type'>VK_FORMAT_FEATURE_BLIT_DST_BIT</"
+                                                                            "span></summary></details>\n"
+                                                                          : ""),  // 0x0800
+                    ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT</span></summary></details>\n"
+                         : ""),  // 0x1000
+                    ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG)
+                         ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                           "class='type'>VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG</span></summary></details>\n"
+                         : ""),  // 0x2000
+                    ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_SRC_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                    "class='type'>VK_FORMAT_FEATURE_TRANSFER_"
+                                                                                    "SRC_BIT_KHR</span></summary></details>\n"
+                                                                                  : ""),  // 0x4000
+                    ((features[i].flags & VK_FORMAT_FEATURE_TRANSFER_DST_BIT_KHR) ? "\t\t\t\t\t\t\t\t<details><summary><span "
+                                                                                    "class='type'>VK_FORMAT_FEATURE_TRANSFER_"
+                                                                                    "DST_BIT_KHR</span></summary></details>\n"
+                                                                                  : ""));  // 0x8000
             }
             fprintf(out, "\t\t\t\t\t\t\t</details>\n");
         } else if (human_readable_output) {
@@ -2415,224 +2574,224 @@
     if (html_output) {
         fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceFeatures</summary>\n");
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>robustBufferAccess                      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>robustBufferAccess                      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.robustBufferAccess);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>fullDrawIndexUint32                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>fullDrawIndexUint32                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.fullDrawIndexUint32);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>imageCubeArray                          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>imageCubeArray                          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.imageCubeArray);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>independentBlend                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>independentBlend                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.independentBlend);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>geometryShader                          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>geometryShader                          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.geometryShader);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>tessellationShader                      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>tessellationShader                      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.tessellationShader);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sampleRateShading                       = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sampleRateShading                       = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sampleRateShading);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>dualSrcBlend                            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>dualSrcBlend                            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.dualSrcBlend);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>logicOp                                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>logicOp                                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.logicOp);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>multiDrawIndirect                       = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>multiDrawIndirect                       = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.multiDrawIndirect);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>drawIndirectFirstInstance               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>drawIndirectFirstInstance               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.drawIndirectFirstInstance);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>depthClamp                              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>depthClamp                              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.depthClamp);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>depthBiasClamp                          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>depthBiasClamp                          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.depthBiasClamp);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>fillModeNonSolid                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>fillModeNonSolid                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.fillModeNonSolid);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>depthBounds                             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>depthBounds                             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.depthBounds);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>wideLines                               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>wideLines                               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.wideLines);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>largePoints                             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>largePoints                             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.largePoints);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>alphaToOne                              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>alphaToOne                              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.alphaToOne);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>multiViewport                           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>multiViewport                           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.multiViewport);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>samplerAnisotropy                       = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>samplerAnisotropy                       = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.samplerAnisotropy);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>textureCompressionETC2                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>textureCompressionETC2                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.textureCompressionETC2);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>textureCompressionASTC_LDR              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>textureCompressionASTC_LDR              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.textureCompressionASTC_LDR);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>textureCompressionBC                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>textureCompressionBC                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.textureCompressionBC);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>occlusionQueryPrecise                   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>occlusionQueryPrecise                   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.occlusionQueryPrecise);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>pipelineStatisticsQuery                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>pipelineStatisticsQuery                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.pipelineStatisticsQuery);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>vertexPipelineStoresAndAtomics          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>vertexPipelineStoresAndAtomics          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.vertexPipelineStoresAndAtomics);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>fragmentStoresAndAtomics                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>fragmentStoresAndAtomics                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.fragmentStoresAndAtomics);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderTessellationAndGeometryPointSize  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderTessellationAndGeometryPointSize  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderTessellationAndGeometryPointSize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderImageGatherExtended               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderImageGatherExtended               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderImageGatherExtended);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageImageExtendedFormats       = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageImageExtendedFormats       = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageImageExtendedFormats);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageImageMultisample           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageImageMultisample           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageImageMultisample);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageImageReadWithoutFormat     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageImageReadWithoutFormat     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageImageReadWithoutFormat);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageImageWriteWithoutFormat    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageImageWriteWithoutFormat    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageImageWriteWithoutFormat);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderUniformBufferArrayDynamicIndexing = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderUniformBufferArrayDynamicIndexing = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderUniformBufferArrayDynamicIndexing);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderSampledImageArrayDynamicIndexing  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderSampledImageArrayDynamicIndexing  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderSampledImageArrayDynamicIndexing);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageBufferArrayDynamicIndexing = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageBufferArrayDynamicIndexing = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageBufferArrayDynamicIndexing);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderStorageImageArrayDynamicIndexing  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderStorageImageArrayDynamicIndexing  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderStorageImageArrayDynamicIndexing);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderClipDistance                      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderClipDistance                      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderClipDistance);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderCullDistance                      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderCullDistance                      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderCullDistance);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderFloat64                           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderFloat64                           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderFloat64);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderInt64                             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderInt64                             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderInt64);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderInt16                             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderInt16                             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderInt16);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderResourceResidency                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderResourceResidency                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderResourceResidency);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>shaderResourceMinLod                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>shaderResourceMinLod                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.shaderResourceMinLod);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseBinding                           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseBinding                           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseBinding);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidencyBuffer                   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidencyBuffer                   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidencyBuffer);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidencyImage2D                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidencyImage2D                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidencyImage2D);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidencyImage3D                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidencyImage3D                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidencyImage3D);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidency2Samples                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidency2Samples                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidency2Samples);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidency4Samples                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidency4Samples                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidency4Samples);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidency8Samples                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidency8Samples                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidency8Samples);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidency16Samples                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidency16Samples                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidency16Samples);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseResidencyAliased                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseResidencyAliased                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.sparseResidencyAliased);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>variableMultisampleRate                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>variableMultisampleRate                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.variableMultisampleRate);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>inheritedQueries                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>inheritedQueries                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 features.inheritedQueries);
         fprintf(out, "\t\t\t\t\t</details>\n");
     } else if (human_readable_output) {
@@ -2767,16 +2926,16 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDevice8BitStorageFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>storageBuffer8BitAccess           = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>storageBuffer8BitAccess           = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b8_store_features->storageBuffer8BitAccess);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>uniformAndStorageBuffer8BitAccess = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>uniformAndStorageBuffer8BitAccess = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b8_store_features->uniformAndStorageBuffer8BitAccess);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>storagePushConstant8              = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>storagePushConstant8              = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b8_store_features->storagePushConstant8);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2793,20 +2952,20 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDevice16BitStorageFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>storageBuffer16BitAccess           = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>storageBuffer16BitAccess           = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b16_store_features->storageBuffer16BitAccess);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>uniformAndStorageBuffer16BitAccess = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>uniformAndStorageBuffer16BitAccess = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b16_store_features->uniformAndStorageBuffer16BitAccess);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>storagePushConstant16              = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>storagePushConstant16              = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b16_store_features->storagePushConstant16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>storageInputOutput16               = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>storageInputOutput16               = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             b16_store_features->storageInputOutput16);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2826,7 +2985,7 @@
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceSamplerYcbcrConversionFeatures</summary>\n");
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>samplerYcbcrConversion = <div class='val'>%u</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>samplerYcbcrConversion = <span class='val'>%u</span></summary></details>\n",
                         sampler_ycbcr_features->samplerYcbcrConversion);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2842,12 +3001,12 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceVariablePointerFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>variablePointersStorageBuffer = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>variablePointersStorageBuffer = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             var_pointer_features->variablePointersStorageBuffer);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>variablePointers              = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>variablePointers              = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             var_pointer_features->variablePointers);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2864,8 +3023,8 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceBlendOperationAdvancedFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendCoherentOperations = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendCoherentOperations = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_features->advancedBlendCoherentOperations);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2880,16 +3039,16 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceMultiviewFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>multiview                   = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>multiview                   = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             multiview_features->multiview);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>multiviewGeometryShader     = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>multiviewGeometryShader     = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             multiview_features->multiviewGeometryShader);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>multiviewTessellationShader = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>multiviewTessellationShader = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             multiview_features->multiviewTessellationShader);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2906,12 +3065,12 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceFloat16Int8Features</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderFloat16 = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderFloat16 = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_int_features->shaderFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderInt8    = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderInt8    = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_int_features->shaderInt8);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2928,12 +3087,12 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceShaderAtomicInt64Features</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderBufferInt64Atomics = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderBufferInt64Atomics = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             shader_atomic_int64_features->shaderBufferInt64Atomics);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderSharedInt64Atomics = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderSharedInt64Atomics = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             shader_atomic_int64_features->shaderSharedInt64Atomics);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2952,12 +3111,12 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceTransformFeedbackFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>transformFeedback = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>transformFeedback = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             transform_feedback_features->transformFeedback);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>geometryStreams   = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>geometryStreams   = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             transform_feedback_features->geometryStreams);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2974,8 +3133,8 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceScalarBlockLayoutFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>scalarBlockLayout = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>scalarBlockLayout = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             scalar_block_layout_features->scalarBlockLayout);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -2991,16 +3150,16 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceFragmentDensityMapFeatures</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>fragmentDensityMap                    = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>fragmentDensityMap                    = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_features->fragmentDensityMap);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>fragmentDensityMapDynamic             = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>fragmentDensityMapDynamic             = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_features->fragmentDensityMapDynamic);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>fragmentDensityMapNonSubsampledImages = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>fragmentDensityMapNonSubsampledImages = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_features->fragmentDensityMapNonSubsampledImages);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -3013,6 +3172,86 @@
                     printf("\tfragmentDensityMapNonSubsampledImages = %" PRIuLEAST32 "\n",
                            fragment_density_map_features->fragmentDensityMapNonSubsampledImages);
                 }
+            } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_PRIORITY_FEATURES_EXT &&
+                       CheckPhysicalDeviceExtensionIncluded(VK_EXT_MEMORY_PRIORITY_EXTENSION_NAME, gpu->device_extensions,
+                                                            gpu->device_extension_count)) {
+                VkPhysicalDeviceMemoryPriorityFeaturesEXT *memory_priority_features =
+                    (VkPhysicalDeviceMemoryPriorityFeaturesEXT *)structure;
+                if (html_output) {
+                    fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceMemoryPriorityFeatures</summary>\n");
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>memoryPriority = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            memory_priority_features->memoryPriority);
+                    fprintf(out, "\t\t\t\t\t</details>\n");
+                } else if (human_readable_output) {
+                    printf("\nVkPhysicalDeviceMemoryPriorityFeatures:\n");
+                    printf("======================================\n");
+                    printf("\tmemoryPriority = %" PRIuLEAST32 "\n", memory_priority_features->memoryPriority);
+                }
+            } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_BUFFER_ADDRESS_FEATURES_EXT &&
+                       CheckPhysicalDeviceExtensionIncluded(VK_EXT_BUFFER_DEVICE_ADDRESS_EXTENSION_NAME, gpu->device_extensions,
+                                                            gpu->device_extension_count)) {
+                VkPhysicalDeviceBufferAddressFeaturesEXT *buffer_address_features =
+                    (VkPhysicalDeviceBufferAddressFeaturesEXT *)structure;
+                if (html_output) {
+                    fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceBufferAddressFeatures</summary>\n");
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>bufferDeviceAddress = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            buffer_address_features->bufferDeviceAddress);
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>bufferDeviceAddressCaptureReplay = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            buffer_address_features->bufferDeviceAddressCaptureReplay);
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>bufferDeviceAddressMultiDevice = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            buffer_address_features->bufferDeviceAddressMultiDevice);
+                    fprintf(out, "\t\t\t\t\t</details>\n");
+                } else if (human_readable_output) {
+                    printf("\nVkPhysicalDeviceBufferAddressFeatures:\n");
+                    printf("======================================\n");
+                    printf("\tbufferDeviceAddress = %" PRIuLEAST32 "\n", buffer_address_features->bufferDeviceAddress);
+                    printf("\tbufferDeviceAddressCaptureReplay = %" PRIuLEAST32 "\n",
+                           buffer_address_features->bufferDeviceAddressCaptureReplay);
+                    printf("\tbufferDeviceAddressMultiDevice = %" PRIuLEAST32 "\n",
+                           buffer_address_features->bufferDeviceAddressMultiDevice);
+                }
+            } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_YCBCR_IMAGE_ARRAYS_FEATURES_EXT &&
+                       CheckPhysicalDeviceExtensionIncluded(VK_EXT_YCBCR_IMAGE_ARRAYS_EXTENSION_NAME, gpu->device_extensions,
+                                                            gpu->device_extension_count)) {
+                VkPhysicalDeviceYcbcrImageArraysFeaturesEXT *ycbcr_image_arrays_features =
+                    (VkPhysicalDeviceYcbcrImageArraysFeaturesEXT *)structure;
+                if (html_output) {
+                    fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceYcbcrImageArraysFeatures</summary>\n");
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>ycbcrImageArrays = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            ycbcr_image_arrays_features->ycbcrImageArrays);
+                    fprintf(out, "\t\t\t\t\t</details>\n");
+                } else if (human_readable_output) {
+                    printf("\nVkPhysicalDeviceYcbcrImageArraysFeatures:\n");
+                    printf("=========================================\n");
+                    printf("\tycbcrImageArrays = %" PRIuLEAST32 "\n", ycbcr_image_arrays_features->ycbcrImageArrays);
+                }
+            } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES_EXT &&
+                       CheckPhysicalDeviceExtensionIncluded(VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME, gpu->device_extensions,
+                                                            gpu->device_extension_count)) {
+                VkPhysicalDeviceHostQueryResetFeaturesEXT *host_query_reset_features =
+                    (VkPhysicalDeviceHostQueryResetFeaturesEXT *)structure;
+                if (html_output) {
+                    fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceHostQueryResetFeatures</summary>\n");
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>hostQueryReset = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            host_query_reset_features->hostQueryReset);
+                    fprintf(out, "\t\t\t\t\t</details>\n");
+                } else if (human_readable_output) {
+                    printf("\nVkPhysicalDeviceHostQueryResetFeatures:\n");
+                    printf("=======================================\n");
+                    printf("\thostQueryReset = %" PRIuLEAST32 "\n", host_query_reset_features->hostQueryReset);
+                }
             }
             place = structure->pNext;
         }
@@ -3023,24 +3262,24 @@
     if (html_output) {
         fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceSparseProperties</summary>\n");
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>residencyStandard2DBlockShape            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>residencyStandard2DBlockShape            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 sparse_props->residencyStandard2DBlockShape);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>residencyStandard2DMultisampleBlockShape = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>residencyStandard2DMultisampleBlockShape = <span "
+                "class='val'>%u</span></summary></details>\n",
                 sparse_props->residencyStandard2DMultisampleBlockShape);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>residencyStandard3DBlockShape            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>residencyStandard3DBlockShape            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 sparse_props->residencyStandard3DBlockShape);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>residencyAlignedMipSize                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>residencyAlignedMipSize                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 sparse_props->residencyAlignedMipSize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>residencyNonResidentStrict               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>residencyNonResidentStrict               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 sparse_props->residencyNonResidentStrict);
         fprintf(out, "\t\t\t\t\t</details>\n");
     } else if (human_readable_output) {
@@ -3068,460 +3307,460 @@
     if (html_output) {
         fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceLimits</summary>\n");
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxImageDimension1D                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxImageDimension1D                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxImageDimension1D);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxImageDimension2D                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxImageDimension2D                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxImageDimension2D);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxImageDimension3D                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxImageDimension3D                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxImageDimension3D);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxImageDimensionCube                   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxImageDimensionCube                   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxImageDimensionCube);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxImageArrayLayers                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxImageArrayLayers                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxImageArrayLayers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTexelBufferElements                  = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTexelBufferElements                  = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxTexelBufferElements);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxUniformBufferRange                   = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxUniformBufferRange                   = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxUniformBufferRange);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxStorageBufferRange                   = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxStorageBufferRange                   = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxStorageBufferRange);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPushConstantsSize                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPushConstantsSize                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPushConstantsSize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxMemoryAllocationCount                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxMemoryAllocationCount                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxMemoryAllocationCount);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxSamplerAllocationCount               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxSamplerAllocationCount               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxSamplerAllocationCount);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>bufferImageGranularity                  = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>bufferImageGranularity                  = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->bufferImageGranularity);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sparseAddressSpaceSize                  = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sparseAddressSpaceSize                  = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->sparseAddressSpaceSize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxBoundDescriptorSets                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxBoundDescriptorSets                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxBoundDescriptorSets);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSamplers           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSamplers           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorSamplers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorUniformBuffers     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorUniformBuffers     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorUniformBuffers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageBuffers     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageBuffers     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorStorageBuffers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSampledImages      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorSampledImages      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorSampledImages);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageImages      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorStorageImages      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorStorageImages);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorInputAttachments   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageDescriptorInputAttachments   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageDescriptorInputAttachments);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxPerStageResources                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxPerStageResources                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxPerStageResources);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetSamplers                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetSamplers                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetSamplers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffers          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffers          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetUniformBuffers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffersDynamic   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetUniformBuffersDynamic   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetUniformBuffersDynamic);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffers          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffers          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetStorageBuffers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffersDynamic   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageBuffersDynamic   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetStorageBuffersDynamic);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetSampledImages           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetSampledImages           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetSampledImages);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageImages           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetStorageImages           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetStorageImages);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDescriptorSetInputAttachments        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDescriptorSetInputAttachments        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDescriptorSetInputAttachments);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxVertexInputAttributes                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxVertexInputAttributes                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxVertexInputAttributes);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxVertexInputBindings                  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxVertexInputBindings                  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxVertexInputBindings);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxVertexInputAttributeOffset           = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxVertexInputAttributeOffset           = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxVertexInputAttributeOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxVertexInputBindingStride             = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxVertexInputBindingStride             = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxVertexInputBindingStride);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxVertexOutputComponents               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxVertexOutputComponents               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxVertexOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationGenerationLevel          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationGenerationLevel          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationGenerationLevel);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationPatchSize                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationPatchSize                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationPatchSize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexInputComponents  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexInputComponents  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationControlPerVertexInputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexOutputComponents = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerVertexOutputComponents = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationControlPerVertexOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerPatchOutputComponents  = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationControlPerPatchOutputComponents  = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationControlPerPatchOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationControlTotalOutputComponents     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationControlTotalOutputComponents     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationControlTotalOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationInputComponents        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationInputComponents        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationEvaluationInputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationOutputComponents       = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTessellationEvaluationOutputComponents       = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxTessellationEvaluationOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxGeometryShaderInvocations            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxGeometryShaderInvocations            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxGeometryShaderInvocations);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxGeometryInputComponents              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxGeometryInputComponents              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxGeometryInputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxGeometryOutputComponents             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxGeometryOutputComponents             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxGeometryOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxGeometryOutputVertices               = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxGeometryOutputVertices               = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxGeometryOutputVertices);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxGeometryTotalOutputComponents        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxGeometryTotalOutputComponents        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxGeometryTotalOutputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFragmentInputComponents              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFragmentInputComponents              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFragmentInputComponents);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFragmentOutputAttachments            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFragmentOutputAttachments            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFragmentOutputAttachments);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFragmentDualSrcAttachments           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFragmentDualSrcAttachments           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFragmentDualSrcAttachments);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFragmentCombinedOutputResources      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFragmentCombinedOutputResources      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFragmentCombinedOutputResources);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeSharedMemorySize              = <div class='val'>0x%" PRIxLEAST32
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeSharedMemorySize              = <span class='val'>0x%" PRIxLEAST32
+                "</span></summary></details>\n",
                 limits->maxComputeSharedMemorySize);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[0]             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[0]             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupCount[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[1]             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[1]             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupCount[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[2]             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupCount[2]             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupCount[2]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupInvocations          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupInvocations          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupInvocations);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[0]              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[0]              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupSize[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[1]              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[1]              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupSize[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[2]              = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxComputeWorkGroupSize[2]              = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxComputeWorkGroupSize[2]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>subPixelPrecisionBits                   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>subPixelPrecisionBits                   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->subPixelPrecisionBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>subTexelPrecisionBits                   = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>subTexelPrecisionBits                   = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->subTexelPrecisionBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>mipmapPrecisionBits                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>mipmapPrecisionBits                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->mipmapPrecisionBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDrawIndexedIndexValue                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDrawIndexedIndexValue                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDrawIndexedIndexValue);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxDrawIndirectCount                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxDrawIndirectCount                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxDrawIndirectCount);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxSamplerLodBias                       = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxSamplerLodBias                       = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->maxSamplerLodBias);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxSamplerAnisotropy                    = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxSamplerAnisotropy                    = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->maxSamplerAnisotropy);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxViewports                            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxViewports                            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxViewports);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxViewportDimensions[0]                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxViewportDimensions[0]                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxViewportDimensions[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxViewportDimensions[1]                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxViewportDimensions[1]                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxViewportDimensions[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>viewportBoundsRange[0]                  = <div "
-                "class='val'>%13f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>viewportBoundsRange[0]                  = <span "
+                "class='val'>%13f</span></summary></details>\n",
                 limits->viewportBoundsRange[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>viewportBoundsRange[1]                  = <div "
-                "class='val'>%13f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>viewportBoundsRange[1]                  = <span "
+                "class='val'>%13f</span></summary></details>\n",
                 limits->viewportBoundsRange[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>viewportSubPixelBits                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>viewportSubPixelBits                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->viewportSubPixelBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minMemoryMapAlignment                   = <div class='val'>" PRINTF_SIZE_T_SPECIFIER
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minMemoryMapAlignment                   = <span class='val'>" PRINTF_SIZE_T_SPECIFIER
+                "</span></summary></details>\n",
                 limits->minMemoryMapAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minTexelBufferOffsetAlignment           = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minTexelBufferOffsetAlignment           = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->minTexelBufferOffsetAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minUniformBufferOffsetAlignment         = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minUniformBufferOffsetAlignment         = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->minUniformBufferOffsetAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minStorageBufferOffsetAlignment         = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minStorageBufferOffsetAlignment         = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->minStorageBufferOffsetAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minTexelOffset                          = <div "
-                "class='val'>%3d</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minTexelOffset                          = <span "
+                "class='val'>%3d</span></summary></details>\n",
                 limits->minTexelOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTexelOffset                          = <div "
-                "class='val'>%3d</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTexelOffset                          = <span "
+                "class='val'>%3d</span></summary></details>\n",
                 limits->maxTexelOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minTexelGatherOffset                    = <div "
-                "class='val'>%3d</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minTexelGatherOffset                    = <span "
+                "class='val'>%3d</span></summary></details>\n",
                 limits->minTexelGatherOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxTexelGatherOffset                    = <div "
-                "class='val'>%3d</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxTexelGatherOffset                    = <span "
+                "class='val'>%3d</span></summary></details>\n",
                 limits->maxTexelGatherOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minInterpolationOffset                  = <div "
-                "class='val'>%9f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minInterpolationOffset                  = <span "
+                "class='val'>%9f</span></summary></details>\n",
                 limits->minInterpolationOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxInterpolationOffset                  = <div "
-                "class='val'>%9f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxInterpolationOffset                  = <span "
+                "class='val'>%9f</span></summary></details>\n",
                 limits->maxInterpolationOffset);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>subPixelInterpolationOffsetBits         = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>subPixelInterpolationOffsetBits         = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->subPixelInterpolationOffsetBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFramebufferWidth                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFramebufferWidth                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFramebufferWidth);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFramebufferHeight                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFramebufferHeight                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFramebufferHeight);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxFramebufferLayers                    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxFramebufferLayers                    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxFramebufferLayers);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>framebufferColorSampleCounts            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>framebufferColorSampleCounts            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->framebufferColorSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>framebufferDepthSampleCounts            = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>framebufferDepthSampleCounts            = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->framebufferDepthSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>framebufferStencilSampleCounts          = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>framebufferStencilSampleCounts          = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->framebufferStencilSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>framebufferNoAttachmentsSampleCounts    = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>framebufferNoAttachmentsSampleCounts    = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->framebufferNoAttachmentsSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxColorAttachments                     = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxColorAttachments                     = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxColorAttachments);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sampledImageColorSampleCounts           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sampledImageColorSampleCounts           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->sampledImageColorSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sampledImageDepthSampleCounts           = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sampledImageDepthSampleCounts           = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->sampledImageDepthSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sampledImageStencilSampleCounts         = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sampledImageStencilSampleCounts         = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->sampledImageStencilSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>sampledImageIntegerSampleCounts         = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>sampledImageIntegerSampleCounts         = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->sampledImageIntegerSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>storageImageSampleCounts                = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>storageImageSampleCounts                = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->storageImageSampleCounts);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxSampleMaskWords                      = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxSampleMaskWords                      = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxSampleMaskWords);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>timestampComputeAndGraphics             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>timestampComputeAndGraphics             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->timestampComputeAndGraphics);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>timestampPeriod                         = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>timestampPeriod                         = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->timestampPeriod);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxClipDistances                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxClipDistances                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxClipDistances);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxCullDistances                        = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxCullDistances                        = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxCullDistances);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>maxCombinedClipAndCullDistances         = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>maxCombinedClipAndCullDistances         = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->maxCombinedClipAndCullDistances);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>discreteQueuePriorities                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>discreteQueuePriorities                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->discreteQueuePriorities);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>pointSizeRange[0]                       = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>pointSizeRange[0]                       = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->pointSizeRange[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>pointSizeRange[1]                       = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>pointSizeRange[1]                       = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->pointSizeRange[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>lineWidthRange[0]                       = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>lineWidthRange[0]                       = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->lineWidthRange[0]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>lineWidthRange[1]                       = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>lineWidthRange[1]                       = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->lineWidthRange[1]);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>pointSizeGranularity                    = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>pointSizeGranularity                    = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->pointSizeGranularity);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>lineWidthGranularity                    = <div "
-                "class='val'>%f</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>lineWidthGranularity                    = <span "
+                "class='val'>%f</span></summary></details>\n",
                 limits->lineWidthGranularity);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>strictLines                             = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>strictLines                             = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->strictLines);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>standardSampleLocations                 = <div "
-                "class='val'>%u</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>standardSampleLocations                 = <span "
+                "class='val'>%u</span></summary></details>\n",
                 limits->standardSampleLocations);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>optimalBufferCopyOffsetAlignment        = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>optimalBufferCopyOffsetAlignment        = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->optimalBufferCopyOffsetAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>optimalBufferCopyRowPitchAlignment      = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>optimalBufferCopyRowPitchAlignment      = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->optimalBufferCopyRowPitchAlignment);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>nonCoherentAtomSize                     = <div class='val'>0x%" PRIxLEAST64
-                "</div></summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>nonCoherentAtomSize                     = <span class='val'>0x%" PRIxLEAST64
+                "</span></summary></details>\n",
                 limits->nonCoherentAtomSize);
         fprintf(out, "\t\t\t\t\t</details>\n");
     } else if (human_readable_output) {
@@ -3801,16 +4040,16 @@
     if (html_output) {
         fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceProperties</summary>\n");
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>apiVersion = <div class='val'>0x%" PRIxLEAST32
-                "</div>  (<div class='val'>%d.%d.%d</div>)</summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>apiVersion = <span class='val'>0x%" PRIxLEAST32
+                "</span>  (<span class='val'>%d.%d.%d</span>)</summary></details>\n",
                 apiVersion, major, minor, patch);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>driverVersion = <div class='val'>%u</div> (<div class='val'>0x%" PRIxLEAST32
-                "</div>)</summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>driverVersion = <span class='val'>%u</span> (<span class='val'>0x%" PRIxLEAST32
+                "</span>)</summary></details>\n",
                 props.driverVersion, props.driverVersion);
-        fprintf(out, "\t\t\t\t\t\t<details><summary>vendorID = <div class='val'>0x%04x</div></summary></details>\n",
+        fprintf(out, "\t\t\t\t\t\t<details><summary>vendorID = <span class='val'>0x%04x</span></summary></details>\n",
                 props.vendorID);
-        fprintf(out, "\t\t\t\t\t\t<details><summary>deviceID = <div class='val'>0x%04x</div></summary></details>\n",
+        fprintf(out, "\t\t\t\t\t\t<details><summary>deviceID = <span class='val'>0x%04x</span></summary></details>\n",
                 props.deviceID);
         fprintf(out, "\t\t\t\t\t\t<details><summary>deviceType = %s</summary></details>\n",
                 VkPhysicalDeviceTypeString(props.deviceType));
@@ -3878,28 +4117,28 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceBlendOperationAdvancedProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendMaxColorAttachments                = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendMaxColorAttachments                = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendMaxColorAttachments);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendIndependentBlend                   = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendIndependentBlend                   = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendIndependentBlend);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedSrcColor           = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedSrcColor           = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendNonPremultipliedSrcColor);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedDstColor           = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendNonPremultipliedDstColor           = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendNonPremultipliedDstColor);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendCorrelatedOverlap                  = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendCorrelatedOverlap                  = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendCorrelatedOverlap);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>advancedBlendAllOperations                      = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>advancedBlendAllOperations                      = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             blend_op_adv_props->advancedBlendAllOperations);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -3925,8 +4164,8 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDevicePointClippingProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>pointClippingBehavior               = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>pointClippingBehavior               = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             pt_clip_props->pointClippingBehavior);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -3942,8 +4181,8 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDevicePushDescriptorProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>maxPushDescriptors                = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>maxPushDescriptors                = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             push_desc_props->maxPushDescriptors);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -3959,8 +4198,8 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceDiscardRectangleProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>maxDiscardRectangles               = <div "
-                            "class='val'>%u</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>maxDiscardRectangles               = <span "
+                            "class='val'>%u</span></summary></details>\n",
                             discard_rect_props->maxDiscardRectangles);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -3974,14 +4213,14 @@
                 VkPhysicalDeviceMultiviewPropertiesKHR *multiview_props = (VkPhysicalDeviceMultiviewPropertiesKHR *)structure;
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceMultiviewProperties</summary>\n");
-                    fprintf(
-                        out,
-                        "\t\t\t\t\t\t<details><summary>maxMultiviewViewCount     = <div class='val'>%u</div></summary></details>\n",
-                        multiview_props->maxMultiviewViewCount);
-                    fprintf(
-                        out,
-                        "\t\t\t\t\t\t<details><summary>maxMultiviewInstanceIndex = <div class='val'>%u</div></summary></details>\n",
-                        multiview_props->maxMultiviewInstanceIndex);
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>maxMultiviewViewCount     = <span "
+                            "class='val'>%u</span></summary></details>\n",
+                            multiview_props->maxMultiviewViewCount);
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>maxMultiviewInstanceIndex = <span "
+                            "class='val'>%u</span></summary></details>\n",
+                            multiview_props->maxMultiviewInstanceIndex);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
                     printf("\nVkPhysicalDeviceMultiviewProperties:\n");
@@ -3995,12 +4234,12 @@
                 if (html_output) {
                     fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceMaintenance3Properties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>maxPerSetDescriptors    = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>maxPerSetDescriptors    = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             maintenance3_props->maxPerSetDescriptors);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>maxMemoryAllocationSize = <div class='val'>%" PRIuLEAST64
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>maxMemoryAllocationSize = <span class='val'>%" PRIuLEAST64
+                            "</span></summary></details>\n",
                             maintenance3_props->maxMemoryAllocationSize);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -4017,8 +4256,8 @@
                     // length modifier so cast the operands and use field width
                     // "2" to fake it.
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>deviceUUID      = <div "
-                            "class='val'>%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x</div></summary></"
+                            "\t\t\t\t\t\t<details><summary>deviceUUID      = <span "
+                            "class='val'>%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x</span></summary></"
                             "details>\n",
                             (uint32_t)id_props->deviceUUID[0], (uint32_t)id_props->deviceUUID[1], (uint32_t)id_props->deviceUUID[2],
                             (uint32_t)id_props->deviceUUID[3], (uint32_t)id_props->deviceUUID[4], (uint32_t)id_props->deviceUUID[5],
@@ -4028,8 +4267,8 @@
                             (uint32_t)id_props->deviceUUID[13], (uint32_t)id_props->deviceUUID[14],
                             (uint32_t)id_props->deviceUUID[15]);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>driverUUID      = <div "
-                            "class='val'>%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x</div></summary></"
+                            "\t\t\t\t\t\t<details><summary>driverUUID      = <span "
+                            "class='val'>%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x</span></summary></"
                             "details>\n",
                             (uint32_t)id_props->driverUUID[0], (uint32_t)id_props->driverUUID[1], (uint32_t)id_props->driverUUID[2],
                             (uint32_t)id_props->driverUUID[3], (uint32_t)id_props->driverUUID[4], (uint32_t)id_props->driverUUID[5],
@@ -4038,19 +4277,20 @@
                             (uint32_t)id_props->driverUUID[11], (uint32_t)id_props->driverUUID[12],
                             (uint32_t)id_props->driverUUID[13], (uint32_t)id_props->driverUUID[14],
                             (uint32_t)id_props->driverUUID[15]);
-                    fprintf(out, "\t\t\t\t\t\t<details><summary>deviceLUIDValid = <div class='val'>%s</div></summary></details>\n",
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>deviceLUIDValid = <span class='val'>%s</span></summary></details>\n",
                             id_props->deviceLUIDValid ? "true" : "false");
                     if (id_props->deviceLUIDValid) {
                         fprintf(out,
-                                "\t\t\t\t\t\t<details><summary>deviceLUID      = <div "
-                                "class='val'>%02x%02x%02x%02x-%02x%02x%02x%02x</div></summary></details>\n",
+                                "\t\t\t\t\t\t<details><summary>deviceLUID      = <span "
+                                "class='val'>%02x%02x%02x%02x-%02x%02x%02x%02x</span></summary></details>\n",
                                 (uint32_t)id_props->deviceLUID[0], (uint32_t)id_props->deviceLUID[1],
                                 (uint32_t)id_props->deviceLUID[2], (uint32_t)id_props->deviceLUID[3],
                                 (uint32_t)id_props->deviceLUID[4], (uint32_t)id_props->deviceLUID[5],
                                 (uint32_t)id_props->deviceLUID[6], (uint32_t)id_props->deviceLUID[7]);
                         fprintf(
                             out,
-                            "\t\t\t\t\t\t<details><summary>deviceNodeMask  = <div class='val'>0x%08x</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>deviceNodeMask  = <span class='val'>0x%08x</span></summary></details>\n",
                             id_props->deviceNodeMask);
                     }
                     fprintf(out, "\t\t\t\t\t</details>\n");
@@ -4090,27 +4330,27 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceDriverProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>driverID   = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>driverID   = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             driver_props->driverID);
                     fprintf(out, "\t\t\t\t\t\t<details><summary>driverName = %s</summary></details>\n", driver_props->driverName);
                     fprintf(out, "\t\t\t\t\t\t<details><summary>driverInfo = %s</summary></details>\n", driver_props->driverInfo);
                     fprintf(out, "\t\t\t\t\t\t<details><summary>conformanceVersion:</summary></details>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>major    = <div class='val'>%" PRIuLEAST8
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>major    = <span class='val'>%" PRIuLEAST8
+                            "</span></summary></details>\n",
                             driver_props->conformanceVersion.major);
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>minor    = <div class='val'>%" PRIuLEAST8
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>minor    = <span class='val'>%" PRIuLEAST8
+                            "</span></summary></details>\n",
                             driver_props->conformanceVersion.minor);
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>subminor = <div class='val'>%" PRIuLEAST8
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>subminor = <span class='val'>%" PRIuLEAST8
+                            "</span></summary></details>\n",
                             driver_props->conformanceVersion.subminor);
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>patch    = <div class='val'>%" PRIuLEAST8
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>patch    = <span class='val'>%" PRIuLEAST8
+                            "</span></summary></details>\n",
                             driver_props->conformanceVersion.patch);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -4133,72 +4373,72 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceFloatControlsProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>separateDenormSettings       = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>separateDenormSettings       = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->separateDenormSettings);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>separateRoundingModeSettings = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>separateRoundingModeSettings = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->separateRoundingModeSettings);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat16 = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat16 = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderSignedZeroInfNanPreserveFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat32 = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat32 = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderSignedZeroInfNanPreserveFloat32);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat64 = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderSignedZeroInfNanPreserveFloat64 = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderSignedZeroInfNanPreserveFloat64);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat16           = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat16           = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormPreserveFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat32           = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat32           = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormPreserveFloat32);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat64           = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormPreserveFloat64           = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormPreserveFloat64);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat16        = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat16        = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormFlushToZeroFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat32        = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat32        = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormFlushToZeroFloat32);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat64        = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderDenormFlushToZeroFloat64        = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderDenormFlushToZeroFloat64);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat16          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat16          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTEFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat32          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat32          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTEFloat32);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat64          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTEFloat64          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTEFloat64);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat16          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat16          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTZFloat16);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat32          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat32          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTZFloat32);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat64          = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>shaderRoundingModeRTZFloat64          = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             float_control_props->shaderRoundingModeRTZFloat64);
                     fprintf(out, "\t\t\t\t\t</details>\n");
                 } else if (human_readable_output) {
@@ -4245,20 +4485,20 @@
                 if (html_output) {
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDevicePCIBusInfoProperties</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>pciDomain   = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>pciDomain   = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             pci_bus_properties->pciDomain);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>pciBus      = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>pciBus      = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             pci_bus_properties->pciBus);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>pciDevice   = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>pciDevice   = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             pci_bus_properties->pciDevice);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>pciFunction = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>pciFunction = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             pci_bus_properties->pciFunction);
                 } else if (human_readable_output) {
                     printf("\nVkPhysicalDevicePCIBusInfoProperties\n");
@@ -4277,53 +4517,53 @@
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceTransformFeedbackProperties</summary>\n");
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackStreams                = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackStreams                = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackStreams);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBuffers                = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBuffers                = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackBuffers);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferSize             = <div class='val'>%" PRIuLEAST64
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferSize             = <span class='val'>%" PRIuLEAST64
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackBufferSize);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackStreamDataSize         = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackStreamDataSize         = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackStreamDataSize);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferDataSize         = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferDataSize         = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackBufferDataSize);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferDataStride       = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>maxTransformFeedbackBufferDataStride       = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->maxTransformFeedbackBufferDataStride);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>transformFeedbackQueries                   = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>transformFeedbackQueries                   = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->transformFeedbackQueries);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>transformFeedbackStreamsLinesTriangles     = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>transformFeedbackStreamsLinesTriangles     = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->transformFeedbackStreamsLinesTriangles);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>transformFeedbackRasterizationStreamSelect = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>transformFeedbackRasterizationStreamSelect = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->transformFeedbackRasterizationStreamSelect);
                     fprintf(
                         out,
-                        "\t\t\t\t\t\t<details><summary>transformFeedbackDraw                      = <div class='val'>%" PRIuLEAST32
-                        "</div></summary></details>\n",
+                        "\t\t\t\t\t\t<details><summary>transformFeedbackDraw                      = <span class='val'>%" PRIuLEAST32
+                        "</span></summary></details>\n",
                         transform_feedback_properties->transformFeedbackDraw);
                 } else if (human_readable_output) {
                     printf("\nVkPhysicalDeviceTransformFeedbackProperties\n");
@@ -4358,23 +4598,25 @@
                     fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceFragmentDensityMapProperties</summary>\n");
                     fprintf(out, "\t\t\t\t\t\t<details><summary>minFragmentDensityTexelSize</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>width = <div class='val'>%" PRIuLEAST32 "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>width = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_properties->minFragmentDensityTexelSize.width);
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>height = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>height = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_properties->minFragmentDensityTexelSize.height);
                     fprintf(out, "\t\t\t\t\t\t<details><summary>maxFragmentDensityTexelSize</summary>\n");
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>width = <div class='val'>%" PRIuLEAST32 "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>width = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_properties->maxFragmentDensityTexelSize.width);
                     fprintf(out,
-                            "\t\t\t\t\t\t\t<details><summary>height = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t\t<details><summary>height = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_properties->maxFragmentDensityTexelSize.height);
                     fprintf(out,
-                            "\t\t\t\t\t\t<details><summary>fragmentDensityInvocations = <div class='val'>%" PRIuLEAST32
-                            "</div></summary></details>\n",
+                            "\t\t\t\t\t\t<details><summary>fragmentDensityInvocations = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
                             fragment_density_map_properties->fragmentDensityInvocations);
                 } else if (human_readable_output) {
                     printf("\nVkPhysicalDeviceFragmentDensityMapProperties\n");
@@ -4388,7 +4630,102 @@
                     printf("\tfragmentDensityInvocations = %" PRIuLEAST32 "\n",
                            fragment_density_map_properties->fragmentDensityInvocations);
                 }
+            } else if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DEPTH_STENCIL_RESOLVE_PROPERTIES_KHR &&
+                       CheckPhysicalDeviceExtensionIncluded(VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME, gpu->device_extensions,
+                                                            gpu->device_extension_count)) {
+                VkPhysicalDeviceDepthStencilResolvePropertiesKHR *depth_stencil_resolve_properties =
+                    (VkPhysicalDeviceDepthStencilResolvePropertiesKHR *)structure;
+                if (html_output) {
+                    fprintf(out, "\n\t\t\t\t\t<details><summary>VkPhysicalDeviceDepthStencilResolveProperties</summary>\n");
+                    fprintf(out, "\t\t\t\t\t\t<details><summary>supportedDepthResolveModes</summary></details>\n");
+                    if (depth_stencil_resolve_properties->supportedDepthResolveModes == 0) {
+                        fprintf(out,
+                                "\t\t\t\t\t\t<details><summary><span "
+                                "class='val'>VK_RESOLVE_MODE_NONE_KHR</span></summary></details>\n");
+                    } else {
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_AVERAGE_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_MIN_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_MIN_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_MAX_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_MAX_BIT_KHR</span></summary></details>\n");
+                    }
+                    fprintf(out, "\t\t\t\t\t\t<details><summary>supportedStencilResolveModes</summary></details>\n");
+                    if (depth_stencil_resolve_properties->supportedStencilResolveModes == 0) {
+                        fprintf(out,
+                                "\t\t\t\t\t\t<details><summary><span "
+                                "class='val'>VK_RESOLVE_MODE_NONE_KHR</span></summary></details>\n");
+                    } else {
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_AVERAGE_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_MIN_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_MIN_BIT_KHR</span></summary></details>\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_MAX_BIT_KHR)
+                            fprintf(out,
+                                    "\t\t\t\t\t\t<details><summary><span "
+                                    "class='val'>VK_RESOLVE_MODE_MAX_BIT_KHR</span></summary></details>\n");
+                    }
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>independentResolveNone = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            depth_stencil_resolve_properties->independentResolveNone);
+                    fprintf(out,
+                            "\t\t\t\t\t\t<details><summary>independentResolve = <span class='val'>%" PRIuLEAST32
+                            "</span></summary></details>\n",
+                            depth_stencil_resolve_properties->independentResolve);
+                } else if (human_readable_output) {
+                    printf("\nVkPhysicalDeviceDepthStencilResolveProperties\n");
+                    printf("============================================\n");
+                    printf("\t\tsupportedDepthResolveModes:\n");
+                    if (depth_stencil_resolve_properties->supportedDepthResolveModes == 0) {
+                        printf("\t\t\tVK_RESOLVE_MODE_NONE_KHR\n");
+                    } else {
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_AVERAGE_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_MIN_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_MIN_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedDepthResolveModes & VK_RESOLVE_MODE_MAX_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_MAX_BIT_KHR\n");
+                    }
+                    printf("\t\tsupportedStencilResolveModes:\n");
+                    if (depth_stencil_resolve_properties->supportedStencilResolveModes == 0) {
+                        printf("\t\t\tVK_RESOLVE_MODE_NONE_KHR\n");
+                    } else {
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_SAMPLE_ZERO_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_AVERAGE_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_AVERAGE_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_MIN_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_MIN_BIT_KHR\n");
+                        if (depth_stencil_resolve_properties->supportedStencilResolveModes & VK_RESOLVE_MODE_MAX_BIT_KHR)
+                            printf("\t\t\tVK_RESOLVE_MODE_MAX_BIT_KHR\n");
+                    }
+                    printf("\t\tindependentResolveNone = %" PRIuLEAST32 "\n",
+                           depth_stencil_resolve_properties->independentResolveNone);
+                    printf("\t\tindependentResolve     = %" PRIuLEAST32 "\n", depth_stencil_resolve_properties->independentResolve);
+                }
             }
+
             place = structure->pNext;
         }
     }
@@ -4430,7 +4767,7 @@
         }
     }
     if (html_output) {
-        fprintf(out, "\tcount = <div class='val'>%d</div></summary>", extension_count);
+        fprintf(out, "\tcount = <span class='val'>%d</span></summary>", extension_count);
         if (extension_count > 0) {
             fprintf(out, "\n");
         }
@@ -4438,7 +4775,7 @@
         printf("\tcount = %d\n", extension_count);
     }
 
-    const bool is_device_type = strcmp(layer_name, "Device") == 0;
+    const bool is_device_type = layer_name && (strcmp(layer_name, "Device") == 0);
     if (is_device_type && json_output) {
         printf(",\n");
         printf("\t\"ArrayOfVkExtensionProperties\": [");
@@ -4450,7 +4787,7 @@
         VkExtensionProperties const *ext_prop = &extension_properties[i];
         if (html_output) {
             fprintf(out, "\t\t\t\t%s<details><summary>", indent);
-            fprintf(out, "<div class='type'>%s</div>: extension revision <div class='val'>%d</div>", ext_prop->extensionName,
+            fprintf(out, "<span class='type'>%s</span>: extension revision <span class='val'>%d</span>", ext_prop->extensionName,
                     ext_prop->specVersion);
             fprintf(out, "</summary></details>\n");
         } else if (human_readable_output) {
@@ -4498,14 +4835,19 @@
         props = *props_const;
     }
 
-    for (struct SurfaceNameWHandle *surface_stuff = gpu->inst->surface_chain; surface_stuff != NULL;
-         surface_stuff = surface_stuff->pNextSurface) {
-        VkResult err = vkGetPhysicalDeviceSurfaceSupportKHR(gpu->obj, id, surface_stuff->surface, &surface_stuff->present_support);
+    bool is_present_platform_agnostic = true;
+    VkBool32 platforms_support_present = VK_FALSE;
+    for (struct SurfaceExtensionNode *sen = gpu->inst->surface_ext_infos_root; sen != NULL; sen = sen->next) {
+        VkResult err = vkGetPhysicalDeviceSurfaceSupportKHR(gpu->obj, id, sen->surface, &sen->supports_present);
         if (err) ERR_EXIT(err);
+
+        const bool first = (sen == gpu->inst->surface_ext_infos_root);
+        if (!first && platforms_support_present != sen->supports_present) is_present_platform_agnostic = false;
+        platforms_support_present = sen->supports_present;
     }
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t<details><summary>VkQueueFamilyProperties[<div class='val'>%d</div>]</summary>\n", id);
+        fprintf(out, "\t\t\t\t\t<details><summary>VkQueueFamilyProperties[<span class='val'>%d</span>]</summary>\n", id);
         fprintf(out, "\t\t\t\t\t\t<details><summary>queueFlags = ");
     } else if (human_readable_output) {
         printf("VkQueueFamilyProperties[%d]:\n", id);
@@ -4533,22 +4875,26 @@
 
     if (html_output) {
         fprintf(out, "</summary></details>\n");
-        fprintf(out, "\t\t\t\t\t\t<details><summary>queueCount         = <div class='val'>%u</div></summary></details>\n",
+        fprintf(out, "\t\t\t\t\t\t<details><summary>queueCount         = <span class='val'>%u</span></summary></details>\n",
                 props.queueCount);
-        fprintf(out, "\t\t\t\t\t\t<details><summary>timestampValidBits = <div class='val'>%u</div></summary></details>\n",
+        fprintf(out, "\t\t\t\t\t\t<details><summary>timestampValidBits = <span class='val'>%u</span></summary></details>\n",
                 props.timestampValidBits);
         fprintf(out,
-                "\t\t\t\t\t\t<details><summary>minImageTransferGranularity = (<div class='val'>%d</div>, <div "
-                "class='val'>%d</div>, <div class='val'>%d</div>)</summary></details>\n",
+                "\t\t\t\t\t\t<details><summary>minImageTransferGranularity = (<span class='val'>%d</span>, <span "
+                "class='val'>%d</span>, <span class='val'>%d</span>)</summary></details>\n",
                 props.minImageTransferGranularity.width, props.minImageTransferGranularity.height,
                 props.minImageTransferGranularity.depth);
-        fprintf(out, "\t\t\t\t\t\t<details><summary>present support</summary>\n");
-        for (struct SurfaceNameWHandle *surface_stuff = gpu->inst->surface_chain; surface_stuff != NULL;
-             surface_stuff = surface_stuff->pNextSurface) {
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>%s = <div class='val'>%s</div></summary></details>\n",
-                    surface_stuff->name, surface_stuff->present_support ? "true" : "false");
+        if (is_present_platform_agnostic) {
+            fprintf(out, "\t\t\t\t\t\t<details><summary>present support = <span class='val'>%s</span></summary></details>\n",
+                    platforms_support_present ? "true" : "false");
+        } else {
+            fprintf(out, "\t\t\t\t\t\t<details open><summary>present support</summary>\n");
+            for (struct SurfaceExtensionNode *sen = gpu->inst->surface_ext_infos_root; sen != NULL; sen = sen->next) {
+                fprintf(out, "\t\t\t\t\t\t\t<details><summary>%s = <span class='val'>%s</span></summary></details>\n", sen->name,
+                        sen->supports_present ? "true" : "false");
+            }
+            fprintf(out, "\t\t\t\t\t\t</details>\n");
         }
-        fprintf(out, "\t\t\t\t\t\t</details>\n");
         fprintf(out, "\t\t\t\t\t</details>\n");
     } else if (human_readable_output) {
         printf("\n");
@@ -4556,10 +4902,13 @@
         printf("\ttimestampValidBits = %u\n", props.timestampValidBits);
         printf("\tminImageTransferGranularity = (%d, %d, %d)\n", props.minImageTransferGranularity.width,
                props.minImageTransferGranularity.height, props.minImageTransferGranularity.depth);
-        printf("\tpresent support:\n");
-        for (struct SurfaceNameWHandle *surface_stuff = gpu->inst->surface_chain; surface_stuff != NULL;
-             surface_stuff = surface_stuff->pNextSurface) {
-            printf("\t\t%s = %s\n", surface_stuff->name, surface_stuff->present_support ? "true" : "false");
+        if (is_present_platform_agnostic) {
+            printf("\tpresent support    = %s\n", platforms_support_present ? "true" : "false");
+        } else {
+            printf("\tpresent support:\n");
+            for (struct SurfaceExtensionNode *sen = gpu->inst->surface_ext_infos_root; sen != NULL; sen = sen->next) {
+                printf("\t\t%s = %s\n", sen->name, sen->supports_present ? "true" : "false");
+            }
         }
     }
     if (json_output) {
@@ -4571,17 +4920,7 @@
         printf("\t\t\t},\n");
         printf("\t\t\t\"queueCount\": %u,\n", props.queueCount);
         printf("\t\t\t\"queueFlags\": %u,\n", props.queueFlags);
-        printf("\t\t\t\"timestampValidBits\": %u,\n", props.timestampValidBits);
-        printf("\t\t\t\"present_support\": {\n");
-        for (struct SurfaceNameWHandle *surface_stuff = gpu->inst->surface_chain; surface_stuff != NULL;
-             surface_stuff = surface_stuff->pNextSurface) {
-            if (surface_stuff->pNextSurface) {
-                printf("\t\t\t\t\"%s\" : %u,\n", surface_stuff->name, surface_stuff->present_support);
-            } else {
-                printf("\t\t\t\t\"%s\" : %u\n", surface_stuff->name, surface_stuff->present_support);
-            }
-        }
-        printf("\t\t\t}\n");
+        printf("\t\t\t\"timestampValidBits\": %u\n", props.timestampValidBits);
         printf("\t\t}");
     }
 
@@ -4614,19 +4953,37 @@
 
 static void AppGpuDumpMemoryProps(const struct AppGpu *gpu, FILE *out) {
     VkPhysicalDeviceMemoryProperties props;
+    struct VkStructureHeader *structure = NULL;
+
+    VkDeviceSize *heapBudget = NULL;
+    VkDeviceSize *heapUsage = NULL;
 
     if (CheckExtensionEnabled(VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME, gpu->inst->inst_extensions,
                               gpu->inst->inst_extensions_count)) {
         const VkPhysicalDeviceMemoryProperties *props2_const = &gpu->memory_props2.memoryProperties;
         props = *props2_const;
+        structure = (struct VkStructureHeader *)gpu->memory_props2.pNext;
     } else {
         const VkPhysicalDeviceMemoryProperties *props_const = &gpu->memory_props;
         props = *props_const;
     }
 
+    while (structure) {
+        if (structure->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT &&
+            CheckPhysicalDeviceExtensionIncluded(VK_EXT_MEMORY_BUDGET_EXTENSION_NAME, gpu->device_extensions,
+                                                 gpu->device_extension_count)) {
+            VkPhysicalDeviceMemoryBudgetPropertiesEXT *mem_budget_props = (VkPhysicalDeviceMemoryBudgetPropertiesEXT *)structure;
+            heapBudget = mem_budget_props->heapBudget;
+            heapUsage = mem_budget_props->heapUsage;
+        }
+
+        structure = (struct VkStructureHeader *)structure->pNext;
+    }
+
     if (html_output) {
         fprintf(out, "\t\t\t\t\t<details><summary>VkPhysicalDeviceMemoryProperties</summary>\n");
-        fprintf(out, "\t\t\t\t\t\t<details><summary>memoryHeapCount = <div class='val'>%u</div></summary>", props.memoryHeapCount);
+        fprintf(out, "\t\t\t\t\t\t<details><summary>memoryHeapCount = <span class='val'>%u</span></summary>",
+                props.memoryHeapCount);
         if (props.memoryHeapCount > 0) {
             fprintf(out, "\n");
         }
@@ -4645,15 +5002,28 @@
         char *mem_size_human_readable = HumanReadable((const size_t)memSize);
 
         if (html_output) {
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryHeaps[<div class='val'>%u</div>]</summary>\n", i);
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryHeaps[<span class='val'>%u</span>]</summary>\n", i);
             fprintf(out,
-                    "\t\t\t\t\t\t\t\t<details><summary>size = <div class='val'>" PRINTF_SIZE_T_SPECIFIER
-                    "</div> (<div class='val'>0x%" PRIxLEAST64 "</div>) (<div class='val'>%s</div>)</summary></details>\n",
+                    "\t\t\t\t\t\t\t\t<details><summary>size = <span class='val'>" PRINTF_SIZE_T_SPECIFIER
+                    "</span> (<span class='val'>0x%" PRIxLEAST64 "</span>) (<span class='val'>%s</span>)</summary></details>\n",
                     (size_t)memSize, memSize, mem_size_human_readable);
+            if (heapBudget != NULL) {
+                fprintf(out,
+                        "\t\t\t\t\t\t\t\t<details><summary>budget = <span class='val'>%" PRIuLEAST64
+                        "</span></summary></details>\n",
+                        heapBudget[i]);
+                fprintf(out,
+                        "\t\t\t\t\t\t\t\t<details><summary>usage = <span class='val'>%" PRIuLEAST64 "</span></summary></details>\n",
+                        heapUsage[i]);
+            }
         } else if (human_readable_output) {
             printf("\tmemoryHeaps[%u] :\n", i);
             printf("\t\tsize          = " PRINTF_SIZE_T_SPECIFIER " (0x%" PRIxLEAST64 ") (%s)\n", (size_t)memSize, memSize,
                    mem_size_human_readable);
+            if (heapBudget != NULL) {
+                fprintf(out, "\t\tbudget        = %" PRIuLEAST64 "\n", heapBudget[i]);
+                fprintf(out, "\t\tusage         = %" PRIuLEAST64 "\n", heapUsage[i]);
+            }
         }
         free(mem_size_human_readable);
 
@@ -4661,8 +5031,9 @@
         if (html_output) {
             fprintf(out, "\t\t\t\t\t\t\t\t<details open><summary>flags</summary>\n");
             fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary>");
-            fprintf(out, (heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) ? "<div class='type'>VK_MEMORY_HEAP_DEVICE_LOCAL_BIT</div>"
-                                                                        : "None");
+            fprintf(out, (heap_flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
+                             ? "<span class='type'>VK_MEMORY_HEAP_DEVICE_LOCAL_BIT</span>"
+                             : "None");
             fprintf(out, "</summary></details>\n");
             fprintf(out, "\t\t\t\t\t\t\t\t</details>\n");
             fprintf(out, "\t\t\t\t\t\t\t</details>\n");
@@ -4695,7 +5066,8 @@
     }
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t\t<details><summary>memoryTypeCount = <div class='val'>%u</div></summary>", props.memoryTypeCount);
+        fprintf(out, "\t\t\t\t\t\t<details><summary>memoryTypeCount = <span class='val'>%u</span></summary>",
+                props.memoryTypeCount);
         if (props.memoryTypeCount > 0) {
             fprintf(out, "\n");
         }
@@ -4708,11 +5080,11 @@
     }
     for (uint32_t i = 0; i < props.memoryTypeCount; ++i) {
         if (html_output) {
-            fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryTypes[<div class='val'>%u</div>]</summary>\n", i);
-            fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>heapIndex = <div class='val'>%u</div></summary></details>\n",
+            fprintf(out, "\t\t\t\t\t\t\t<details><summary>memoryTypes[<span class='val'>%u</span>]</summary>\n", i);
+            fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>heapIndex = <span class='val'>%u</span></summary></details>\n",
                     props.memoryTypes[i].heapIndex);
             fprintf(out,
-                    "\t\t\t\t\t\t\t\t<details open><summary>propertyFlags = <div class='val'>0x%" PRIxLEAST32 "</div></summary>",
+                    "\t\t\t\t\t\t\t\t<details open><summary>propertyFlags = <span class='val'>0x%" PRIxLEAST32 "</span></summary>",
                     props.memoryTypes[i].propertyFlags);
             if (props.memoryTypes[i].propertyFlags == 0) {
                 fprintf(out, "</details>\n");
@@ -4740,30 +5112,29 @@
         if (html_output) {
             if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT</span></summary></details>\n");
             if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT</span></summary></details>\n");
             if (flags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_HOST_COHERENT_BIT</span></summary></details>\n");
             if (flags & VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_HOST_CACHED_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_HOST_CACHED_BIT</span></summary></details>\n");
             if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT</span></summary></details>\n");
             if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT)
                 fprintf(out,
-                        "\t\t\t\t\t\t\t\t\t<details><summary><div "
-                        "class='type'>VK_MEMORY_PROPERTY_PROTECTED_BIT</div></summary></details>\n");
+                        "\t\t\t\t\t\t\t\t\t<details><summary><span "
+                        "class='type'>VK_MEMORY_PROPERTY_PROTECTED_BIT</span></summary></details>\n");
             if (props.memoryTypes[i].propertyFlags > 0) fprintf(out, "\t\t\t\t\t\t\t\t</details>\n");
-            fprintf(out, "\t\t\t\t\t\t\t</details>\n");
         } else if (human_readable_output) {
             if (flags & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT\n");
             if (flags & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_HOST_VISIBLE_BIT\n");
@@ -4772,7 +5143,114 @@
             if (flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT\n");
             if (flags & VK_MEMORY_PROPERTY_PROTECTED_BIT) printf("\t\t\tVK_MEMORY_PROPERTY_PROTECTED_BIT\n");
         }
+
+        if (human_readable_output) {
+            printf("\t\tusable for:\n");
+            const uint32_t memtype_bit = 1 << i;
+
+            for (VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; tiling < ARRAY_SIZE(gpu->mem_type_res_support.image); ++tiling) {
+                printf("\t\t\t%s: ", VkTilingString(tiling));
+
+                bool first = true;
+                for (size_t fmt_i = 0; fmt_i < ARRAY_SIZE(gpu->mem_type_res_support.image[tiling]); ++fmt_i) {
+                    const struct MemImageSupport *image_support = &gpu->mem_type_res_support.image[tiling][fmt_i];
+                    const bool regular_compatible =
+                        image_support->regular_supported && (image_support->regular_memtypes & memtype_bit);
+                    const bool sparse_compatible =
+                        image_support->sparse_supported && (image_support->sparse_memtypes & memtype_bit);
+                    const bool transient_compatible =
+                        image_support->transient_supported && (image_support->transient_memtypes & memtype_bit);
+
+                    if (regular_compatible || sparse_compatible || transient_compatible) {
+                        if (!first) printf(", ");
+                        first = false;
+
+                        if (fmt_i == 0) {
+                            printf("color images");
+                        } else {
+                            printf("%s", VkFormatString(gpu->mem_type_res_support.image[tiling][fmt_i].format));
+                        }
+
+                        if (regular_compatible && !sparse_compatible && !transient_compatible && image_support->sparse_supported &&
+                            image_support->transient_supported) {
+                            printf("(non-sparse, non-transient)");
+                        } else if (regular_compatible && !sparse_compatible && image_support->sparse_supported) {
+                            if (image_support->sparse_supported) printf("(non-sparse)");
+                        } else if (regular_compatible && !transient_compatible && image_support->transient_supported) {
+                            if (image_support->transient_supported) printf("(non-transient)");
+                        } else if (!regular_compatible && sparse_compatible && !transient_compatible &&
+                                   image_support->sparse_supported) {
+                            if (image_support->sparse_supported) printf("(sparse only)");
+                        } else if (!regular_compatible && !sparse_compatible && transient_compatible &&
+                                   image_support->transient_supported) {
+                            if (image_support->transient_supported) printf("(transient only)");
+                        } else if (!regular_compatible && sparse_compatible && transient_compatible &&
+                                   image_support->sparse_supported && image_support->transient_supported) {
+                            printf("(sparse and transient only)");
+                        }
+                    }
+                }
+
+                if (first) printf("None");
+
+                printf("\n");
+            }
+        } else if (html_output) {
+            fprintf(out, "\t\t\t\t\t\t\t\t<details><summary>usable for</summary>\n");
+            const uint32_t memtype_bit = 1 << i;
+
+            for (VkImageTiling tiling = VK_IMAGE_TILING_OPTIMAL; tiling < ARRAY_SIZE(gpu->mem_type_res_support.image); ++tiling) {
+                fprintf(out, "\t\t\t\t\t\t\t\t\t<details><summary>%s</summary>\n", VkTilingString(tiling));
+
+                bool first = true;
+                for (size_t fmt_i = 0; fmt_i < ARRAY_SIZE(gpu->mem_type_res_support.image[tiling]); ++fmt_i) {
+                    const struct MemImageSupport *image_support = &gpu->mem_type_res_support.image[tiling][fmt_i];
+                    const bool regular_compatible =
+                        image_support->regular_supported && (image_support->regular_memtypes & memtype_bit);
+                    const bool sparse_compatible =
+                        image_support->sparse_supported && (image_support->sparse_memtypes & memtype_bit);
+                    const bool transient_compatible =
+                        image_support->transient_supported && (image_support->transient_memtypes & memtype_bit);
+
+                    if (regular_compatible || sparse_compatible || transient_compatible) {
+                        first = false;
+
+                        if (fmt_i == 0) {
+                            fprintf(out, "\t\t\t\t\t\t\t\t\t\t<details><summary>color images</summary>\n");
+                        } else {
+                            fprintf(out, "\t\t\t\t\t\t\t\t\t\t<details><summary>%s</summary>\n",
+                                    VkFormatString(gpu->mem_type_res_support.image[tiling][fmt_i].format));
+                        }
+
+                        fprintf(out,
+                                "\t\t\t\t\t\t\t\t\t\t\t<details><summary><span class=\"type\">regular image</span> = <span "
+                                "class=\"val\">%s</span></summary></details>\n",
+                                regular_compatible ? "supported" : "not supported");
+                        fprintf(out,
+                                "\t\t\t\t\t\t\t\t\t\t\t<details><summary><span "
+                                "class=\"type\">VK_IMAGE_CREATE_SPARSE_BINDING_BIT</span> "
+                                "= <span class=\"val\">%s</span></summary></details>\n",
+                                sparse_compatible ? "supported" : "not supported");
+                        fprintf(out,
+                                "\t\t\t\t\t\t\t\t\t\t\t<details><summary><span "
+                                "class=\"type\">VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT</span> = <span "
+                                "class=\"val\">%s</span></summary></details>\n",
+                                transient_compatible ? "supported" : "not supported");
+
+                        fprintf(out, "\t\t\t\t\t\t\t\t\t\t</details>\n");
+                    }
+                }
+
+                if (first) fprintf(out, "<details><summary><span class=\"type\">None</span></summary></details>");
+
+                fprintf(out, "\t\t\t\t\t\t\t\t\t</details>\n");
+            }
+
+            fprintf(out, "\t\t\t\t\t\t\t\t</details>\n");
+            fprintf(out, "\t\t\t\t\t\t\t</details>\n");
+        }
     }
+
     if (html_output) {
         if (props.memoryTypeCount > 0) {
             fprintf(out, "\t\t\t\t\t\t");
@@ -4853,7 +5331,7 @@
                          FILE *out) {
     if (html_output) {
         fprintf(out, "\t\t\t\t<details><summary>Device Group Properties (Group %u)</summary>\n", id);
-        fprintf(out, "\t\t\t\t\t<details><summary>physicalDeviceCount = <div class='val'>%u</div></summary>\n",
+        fprintf(out, "\t\t\t\t\t<details><summary>physicalDeviceCount = <span class='val'>%u</span></summary>\n",
                 group->physicalDeviceCount);
     } else if (human_readable_output) {
         printf("\tDevice Group Properties (Group %u) :\n", id);
@@ -4872,7 +5350,7 @@
     // Output information to the user.
     for (uint32_t i = 0; i < group->physicalDeviceCount; ++i) {
         if (html_output) {
-            fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
+            fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <span class='val'>%d</span>)</summary></details>\n",
                     props[i].deviceName, i);
         } else if (human_readable_output) {
             printf("\n\t\t\t%s (ID: %d)\n", props[i].deviceName, i);
@@ -4884,7 +5362,7 @@
     }
 
     if (html_output) {
-        fprintf(out, "\t\t\t\t\t<details><summary>subsetAllocation = <div class='val'>%u</div></summary></details>\n",
+        fprintf(out, "\t\t\t\t\t<details><summary>subsetAllocation = <span class='val'>%u</span></summary></details>\n",
                 group->subsetAllocation);
     } else if (human_readable_output) {
         printf("\n\t\tsubsetAllocation = %u\n", group->subsetAllocation);
@@ -4942,14 +5420,14 @@
 
         for (uint32_t i = 0; i < group->physicalDeviceCount; i++) {
             if (html_output) {
-                fprintf(out, "\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
+                fprintf(out, "\t\t\t\t\t<details><summary>%s (ID: <span class='val'>%d</span>)</summary></details>\n",
                         props[i].deviceName, i);
                 fprintf(out, "\t\t\t\t\t<details><summary>Can present images from the following devices:</summary>\n");
                 if (group_capabilities.presentMask[i] != 0) {
                     for (uint32_t j = 0; j < group->physicalDeviceCount; ++j) {
                         uint32_t mask = 1 << j;
                         if (group_capabilities.presentMask[i] & mask) {
-                            fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <div class='val'>%d</div>)</summary></details>\n",
+                            fprintf(out, "\t\t\t\t\t\t<details><summary>%s (ID: <span class='val'>%d</span>)</summary></details>\n",
                                     props[j].deviceName, j);
                         }
                     }
@@ -5081,6 +5559,10 @@
 
     if (html_output) {
         out = fopen("vulkaninfo.html", "w");
+        if (!out) {
+            printf("Unable to open vulkaninfo.html for writing\n");
+            return 1;
+        }
         PrintHtmlHeader(out);
         fprintf(out, "\t\t\t<details><summary>");
     } else if (human_readable_output) {
@@ -5092,7 +5574,7 @@
         fprintf(out, "Vulkan Instance Version: ");
     }
     if (html_output) {
-        fprintf(out, "<div class='val'>%d.%d.%d</div></summary></details>\n", inst.vulkan_major, inst.vulkan_minor,
+        fprintf(out, "<span class='val'>%d.%d.%d</span></summary></details>\n", inst.vulkan_major, inst.vulkan_minor,
                 inst.vulkan_patch);
         fprintf(out, "\t\t\t<br />\n");
     } else if (human_readable_output) {
@@ -5142,7 +5624,7 @@
 
     //---Layer-Device-Extensions---
     if (html_output) {
-        fprintf(out, "\t\t\t<details><summary>Layers: count = <div class='val'>%d</div></summary>", inst.global_layer_count);
+        fprintf(out, "\t\t\t<details><summary>Layers: count = <span class='val'>%d</span></summary>", inst.global_layer_count);
         if (inst.global_layer_count > 0) {
             fprintf(out, "\n");
         }
@@ -5168,9 +5650,9 @@
 
         if (html_output) {
             fprintf(out, "\t\t\t\t<details><summary>");
-            fprintf(out, "<div class='type'>%s</div> (%s) Vulkan version <div class='val'>%s</div>, ", layer_prop->layerName,
+            fprintf(out, "<span class='type'>%s</span> (%s) Vulkan version <span class='val'>%s</span>, ", layer_prop->layerName,
                     (char *)layer_prop->description, spec_version);
-            fprintf(out, "layer version <div class='val'>%s</div></summary>\n", layer_version);
+            fprintf(out, "layer version <span class='val'>%s</span></summary>\n", layer_version);
             AppDumpExtensions("\t\t", "Layer", inst.global_layers[i].extension_count, inst.global_layers[i].extension_properties,
                               out);
         } else if (human_readable_output) {
@@ -5193,7 +5675,7 @@
         }
 
         if (html_output) {
-            fprintf(out, "\t\t\t\t\t<details><summary>Devices count = <div class='val'>%d</div></summary>\n", gpu_count);
+            fprintf(out, "\t\t\t\t\t<details><summary>Devices count = <span class='val'>%d</span></summary>\n", gpu_count);
         } else if (human_readable_output) {
             printf("\tDevices \tcount = %d\n", gpu_count);
         }
@@ -5203,7 +5685,7 @@
         for (uint32_t j = 0; j < gpu_count; ++j) {
             if (html_output) {
                 fprintf(out, "\t\t\t\t\t\t<details><summary>");
-                fprintf(out, "GPU id: <div class='val'>%u</div> (%s)</summary></details>\n", j, gpus[j].props.deviceName);
+                fprintf(out, "GPU id: <span class='val'>%u</span> (%s)</summary></details>\n", j, gpus[j].props.deviceName);
             } else if (human_readable_output) {
                 printf("\t\tGPU id       : %u (%s)\n", j, gpus[j].props.deviceName);
             }
@@ -5274,58 +5756,81 @@
 
 //--WIN32--
 #ifdef VK_USE_PLATFORM_WIN32_KHR
-    struct SurfaceExtensionInfo surface_ext_win32;
-    surface_ext_win32.name = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
-    surface_ext_win32.create_window = AppCreateWin32Window;
-    surface_ext_win32.create_surface = AppCreateWin32Surface;
-    surface_ext_win32.destroy_window = AppDestroyWin32Window;
-    AppDumpSurfaceExtension(&inst, gpus, gpu_count, &surface_ext_win32, &format_count, &present_mode_count, out);
+    struct SurfaceExtensionNode surface_ext_win32;
+    if (CheckExtensionEnabled(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
+        surface_ext_win32.name = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
+        surface_ext_win32.create_window = AppCreateWin32Window;
+        surface_ext_win32.create_surface = AppCreateWin32Surface;
+        surface_ext_win32.destroy_window = AppDestroyWin32Window;
+
+        surface_ext_win32.next = inst.surface_ext_infos_root;
+        inst.surface_ext_infos_root = &surface_ext_win32;
+    }
 #endif
 //--XCB--
 #ifdef VK_USE_PLATFORM_XCB_KHR
-    struct SurfaceExtensionInfo surface_ext_xcb;
-    surface_ext_xcb.name = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
-    surface_ext_xcb.create_window = AppCreateXcbWindow;
-    surface_ext_xcb.create_surface = AppCreateXcbSurface;
-    surface_ext_xcb.destroy_window = AppDestroyXcbWindow;
-    if (has_display) {
-        AppDumpSurfaceExtension(&inst, gpus, gpu_count, &surface_ext_xcb, &format_count, &present_mode_count, out);
+    struct SurfaceExtensionNode surface_ext_xcb;
+    if (CheckExtensionEnabled(VK_KHR_XCB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
+        surface_ext_xcb.name = VK_KHR_XCB_SURFACE_EXTENSION_NAME;
+        surface_ext_xcb.create_window = AppCreateXcbWindow;
+        surface_ext_xcb.create_surface = AppCreateXcbSurface;
+        surface_ext_xcb.destroy_window = AppDestroyXcbWindow;
+        if (has_display) {
+            surface_ext_xcb.next = inst.surface_ext_infos_root;
+            inst.surface_ext_infos_root = &surface_ext_xcb;
+        }
     }
 #endif
 //--XLIB--
 #ifdef VK_USE_PLATFORM_XLIB_KHR
-    struct SurfaceExtensionInfo surface_ext_xlib;
-    surface_ext_xlib.name = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
-    surface_ext_xlib.create_window = AppCreateXlibWindow;
-    surface_ext_xlib.create_surface = AppCreateXlibSurface;
-    surface_ext_xlib.destroy_window = AppDestroyXlibWindow;
-    if (has_display) {
-        AppDumpSurfaceExtension(&inst, gpus, gpu_count, &surface_ext_xlib, &format_count, &present_mode_count, out);
+    struct SurfaceExtensionNode surface_ext_xlib;
+    if (CheckExtensionEnabled(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
+        surface_ext_xlib.name = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
+        surface_ext_xlib.create_window = AppCreateXlibWindow;
+        surface_ext_xlib.create_surface = AppCreateXlibSurface;
+        surface_ext_xlib.destroy_window = AppDestroyXlibWindow;
+        if (has_display) {
+            surface_ext_xlib.next = inst.surface_ext_infos_root;
+            inst.surface_ext_infos_root = &surface_ext_xlib;
+        }
     }
 #endif
 //--MACOS--
 #ifdef VK_USE_PLATFORM_MACOS_MVK
-    struct SurfaceExtensionInfo surface_ext_macos;
-    surface_ext_macos.name = VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
-    surface_ext_macos.create_window = AppCreateMacOSWindow;
-    surface_ext_macos.create_surface = AppCreateMacOSSurface;
-    surface_ext_macos.destroy_window = AppDestroyMacOSWindow;
-    AppDumpSurfaceExtension(&inst, gpus, gpu_count, &surface_ext_macos, &format_count, &present_mode_count, out);
+    struct SurfaceExtensionNode surface_ext_macos;
+    if (CheckExtensionEnabled(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
+        surface_ext_macos.name = VK_MVK_MACOS_SURFACE_EXTENSION_NAME;
+        surface_ext_macos.create_window = AppCreateMacOSWindow;
+        surface_ext_macos.create_surface = AppCreateMacOSSurface;
+        surface_ext_macos.destroy_window = AppDestroyMacOSWindow;
+
+        surface_ext_macos.next = inst.surface_ext_infos_root;
+        inst.surface_ext_infos_root = &surface_ext_macos;
+    }
 #endif
 //--WAYLAND--
 #ifdef VK_USE_PLATFORM_WAYLAND_KHR
-    struct SurfaceExtensionInfo surface_ext_wayland;
-    surface_ext_wayland.name = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
-    surface_ext_wayland.create_window = AppCreateWaylandWindow;
-    surface_ext_wayland.create_surface = AppCreateWaylandSurface;
-    surface_ext_wayland.destroy_window = AppDestroyWaylandWindow;
-    if (has_wayland_display) {
-        AppDumpSurfaceExtension(&inst, gpus, gpu_count, &surface_ext_wayland, &format_count, &present_mode_count, out);
+    struct SurfaceExtensionNode surface_ext_wayland;
+    if (CheckExtensionEnabled(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, inst.inst_extensions, inst.inst_extensions_count)) {
+        surface_ext_wayland.name = VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME;
+        surface_ext_wayland.create_window = AppCreateWaylandWindow;
+        surface_ext_wayland.create_surface = AppCreateWaylandSurface;
+        surface_ext_wayland.destroy_window = AppDestroyWaylandWindow;
+        if (has_wayland_display) {
+            surface_ext_wayland.next = inst.surface_ext_infos_root;
+            inst.surface_ext_infos_root = &surface_ext_wayland;
+        }
     }
 #endif
-
     // TODO: Android
-    if (!format_count && !present_mode_count) {
+
+    for (struct SurfaceExtensionNode *sen = inst.surface_ext_infos_root; sen != NULL; sen = sen->next) {
+        sen->create_window(&inst);
+        sen->surface = sen->create_surface(&inst);
+        AppDumpSurfaceExtension(&inst, gpus, gpu_count, sen, &format_count, &present_mode_count, out);
+    }
+
+    if (!inst.surface_ext_infos_root) {
         if (html_output) {
             fprintf(out, "\t\t\t\t<details><summary>None found</summary></details>\n");
         } else if (human_readable_output) {
@@ -5407,7 +5912,11 @@
     free(gpus);
     free(objs);
 
-    AppDestroySurfaceChain(&inst);
+    for (struct SurfaceExtensionNode *sen = inst.surface_ext_infos_root; sen != NULL; sen = sen->next) {
+        AppDestroySurface(&inst, sen->surface);
+        sen->destroy_window(&inst);
+    }
+
     AppDestroyInstance(&inst);
 
     if (html_output) {